创新实训 12

2021SC@SDUSC

这次我们继续分析Security模块

SecurityConfig

首先我们看到 SecurityConfig

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	// ...
}

SecurityConfig上面启用了三个注解,其中第一个注解Configuration不用过多解释,其为声明一个Spring Bean,

@EnableWebSecurity

这个注解的作用是告诉Spring容器,我们有一个Spring Security的配置

@EnableGlobalMethodSecurity

开启全局的方法安全

这个的作用是能够在调用某一个方法之时进行一些安全鉴定工作

包括前置任务和后置任务等

成员

@Autowired
UserDetailsService ds2ManagerUserDetailsService;

这个UserDetailService是自动绑定的,但是并没有在Security模块中发现对应的Bean

观察了其他需要UserDetailService的模块,他们都有一个UserDetailService的实现,却基本没有配置他们的地方。

并且构建项目时需要调用父模块的build,其他子模块单独打包会出现错误

由此可见,这里的UserDetailService在打包时会动态的绑定到对应的模块所提供的UserDetailService,以实现解耦

重载方法

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(ds2ManagerUserDetailsService)
        .passwordEncoder(passwordEncoder());
}

该方法告诉容器应该采用哪个用户数据服务,并且给出密码的编码器

编码器是简单的 BCryptPasswordEncoder

@Override
protected void configure(HttpSecurity http) throws Exception {
    // 异常处理
    http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint())
        .and()
        // 放行login,register
        .authorizeRequests()
        .antMatchers("/login", "/register").permitAll()
        .antMatchers("/hello", "/img/get_by_id").permitAll()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
        .and()
        // 关闭跨域攻击
        .csrf().disable()
        // 关闭session处理
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}

这个方法中对于一些情况进行了配置,比如说给出了authenticationEntryPoint,允许了一些方法不需要安全检测直接同行,关闭了跨域攻击,关闭了session处理等

下面还声明了Filter

restAuthenticationEntryPoint

RestAuthenticationEntryPoint实现了接口 AuthenticationEntryPointcommence 方法,当用户请求处理遇到了认证异常时,会被 ExceptionTranslationFilter 接住,并且调用 commence 方法来开启特定的认证流程 , 即 authentication schema

security模块中实现的逻辑是直接返回报错信息:

public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Cache-Control","no-cache");
    response.setCharacterEncoding("UTF-8");
    response.setContentType("application/json");
										response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(authException.getMessage())));
    response.getWriter().flush();
}
HttpSecurity.addFilterBefore

这个方法是将你提供的第一个参数对应的Filter加载第二个参数对应的Filter前面

我们可以查看源码:

@Override
public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) {
    this.comparator.registerBefore(filter.getClass(), beforeFilter);
    return addFilter(filter);
}

compatator是 FilterComparator 的实例

FilterComparator 中有一个有序的filter HashMap,是以class为键,优先级为值

这也意味着每种过滤器都是唯一存在的

FilterComparator() {
		Step order = new Step(INITIAL_ORDER, ORDER_STEP);
		put(ChannelProcessingFilter.class, order.next());
		order.next(); // gh-8105
		put(WebAsyncManagerIntegrationFilter.class, order.next());
		put(SecurityContextPersistenceFilter.class, order.next());
		put(HeaderWriterFilter.class, order.next());
//...
		put(UsernamePasswordAuthenticationFilter.class, order.next());
//...
	}

order的初始值是100,

每个filter之间间隔了ORDER_STEP - 1个order,用于塞入自定义的filter

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值