1.在web容器中注册过滤器链

/**
 * 通过继承AbstractSecurityWebApplicationInitializer类, 
 * 该已经实现了springSecurityFilterChain的注册 
 *
 */
public class SpringSecurityInitConfig extends AbstractSecurityWebApplicationInitializer {


}

实现了springSecurityFilterChain注册的源码

public abstract class AbstractSecurityWebApplicationInitializer
        implements WebApplicationInitializer {

    private static final String SERVLET_CONTEXT_PREFIX = "org.springframework.web.servlet.FrameworkServlet.CONTEXT.";

    public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";

    private final Class<?>[] configurationClasses;


//加载时候调用onStartup方法
public final void onStartup(ServletContext servletContext) throws ServletException {
        beforeSpringSecurityFilterChain(servletContext);
        if (this.configurationClasses != null) {
            AnnotationConfigWebApplicationContext rootAppContext = new     AnnotationConfigWebApplicationContext();
            rootAppContext.register(this.configurationClasses);
            servletContext.addListener(new ContextLoaderListener(rootAppContext));
        }
        if (enableHttpSessionEventPublisher()) {
            servletContext.addListener(
                    "org.springframework.security.web.session.HttpSessionEventPublisher");
        }
        servletContext.setSessionTrackingModes(getSessionTrackingModes());
        //调用添加过滤器链方法
        insertSpringSecurityFilterChain(servletContext);
        afterSpringSecurityFilterChain(servletContext);
    }


private void insertSpringSecurityFilterChain(ServletContext servletContext) {
        String filterName = DEFAULT_FILTER_NAME;
        DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(
                filterName);
        String contextAttribute = getWebApplicationContextAttribute();
        if (contextAttribute != null) {
            springSecurityFilterChain.setContextAttribute(contextAttribute);
        }
        //调用注册过滤器链方法
        registerFilter(servletContext, true, filterName, springSecurityFilterChain);
    }

//注册过滤器链的方法
private final void registerFilter(ServletContext servletContext,
            boolean insertBeforeOtherFilters, String filterName, Filter filter) {
        Dynamic registration = servletContext.addFilter(filterName, filter);
        if (registration == null) {
            throw new IllegalStateException(
                    "Duplicate Filter registration for '" + filterName
                            + "'. Check to ensure the Filter is only configured once.");
        }
        registration.setAsyncSupported(isAsyncSecuritySupported());
        EnumSet<DispatcherType> dispatcherTypes = getSecurityDispatcherTypes();
        registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters,
                "/*");
    }

2.springSecurity配置文件

   Filter在web.xml中配置的只是一个代理,而真正起作用的Filter是作为Bean配置在Spring中的。web.xml中的代理依次调用这些Bean,就实现了对Web资源的保护,同时这些Filter作为Bean被Spring管理,所以实现AOP也很简单,一举两得啊。

package cn.it.travel.config;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import cn.it.travel.service.UserService;



/**
 * 1.添加@EnableWebSecurity  创建过滤器执行链给spring容器管理 springSecurityFilterChain
 * 2.继承WebSecurityConfigurerAdapter 目的是重写父类的配置方法 应用自己添加的配置
 * 3.注解@EnableGlobalMethodSecurity  开启注解拦截方法的请求  
 *      prePostEnabled 设置在请求方法之前拦截auth方法,进行权限校验 
 *
 */

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private UserService userService;

    /**
     * configure(AuthenticationManagerBuilder auth)方法是用于配置
     * 权限验证登陆管理
     * */

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);

        /**
         * 自定义配置验证的service类 : 目的是查询数据库读取所有的用户权限  
         * 采用密文验证  :passwordEncoder
         * 加密方式为      :getBCryptPasswordEncoder()
         */
        auth.userDetailsService(userService).passwordEncoder(getBCryptPasswordEncoder());
    }

    /**
     * 将加密方式的配置对象送入容器 
     */
    @Bean
    public BCryptPasswordEncoder  getBCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * configure(HttpSecurity http) 用于请求回调拦截的配置
     * */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //添加不需要认证的路径
                .antMatchers("/login.jsp", "/login.do", "/css/**",
                        "/img/**", "/plugins/**").permitAll()
                //任何请求需要认证
                .anyRequest().authenticated()
                //权限前缀不要给
                //.anyRequest().hasRole("ACCESS")
                //.anyRequest().hasAnyAuthority()
                //.anyRequest().fullyAuthenticated()
                //关闭csrf 关闭跨域的验证
                .and().csrf().disable()
                //自定义配置登陆页面
                .formLogin().loginPage("/login.jsp")
                //自定义登陆请求地址
                .loginProcessingUrl("/login.do").
                //验证成功的跳转页面
                successForwardUrl("/index.jsp").
                //验证失败的跳转路径
                failureForwardUrl("/failer.jsp")
                //退出的请求路径 
                .and().logout().logoutUrl("/logout.do").
                //退出请求后销毁session
                invalidateHttpSession(true).
                //退出成功跳转的页面
                logoutSuccessUrl("/login.jsp")
                //权限不足跳转的路径
                .and().exceptionHandling().accessDeniedPage("/accessDenied.jsp");
    }


}

3 将配置springSecurity的配置类加载到spring容器中

public class AppConfig implements WebApplicationInitializer{

        //2.1创建AnnotationConfigWebApplicationContext
        AnnotationConfigWebApplicationContext springContext = new AnnotationConfigWebApplicationContext();
        //2.2spring的配置类  springSecurity的配置类
        springContext.register(SpringConfig.class,SpringSecurityConfig.class);

4.权限的使用

在业务层方法上通过注解@PreAuthorize,配置调用方法需要的权限:
@PreAuthorize(“hasAuthority(‘PRODUCT_LIST’)”)


    /**
     * 
     * 查询所有商品
     * @PreAuthorize("hasAuthority('PRODUCT_LIST')")
     * 配置调用该业务层方法需要的权限为:PRODUCT_LIST
     * */
    @PreAuthorize("hasAuthority('PRODUCT_LIST')")
    @Transactional(propagation = Propagation.SUPPORTS ,readOnly = true)
    public PageInfo findAllProduct(Integer pageNum,Integer pageSize){
         PageHelper.startPage(pageNum, pageSize);
         List<Product> products = productDao.findAllProduct();
         PageInfo pageInfo = new PageInfo(products);
         return pageInfo;
    };
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐