在学习这门课的时候,实现各种功能时进行了各种配置。我想将各种配置综合讲述一下。
首先自定义配置类,需要继承WebSecurityConfigurerAdapter
这个类。
在这个类里面做了一些默认配置。
1 2 3 4
| @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ .... }
|
更改PasswordEncoder
的实现为BCryptPasswordEncoder
。
1 2 3 4
| @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); }
|
注入AuthenticationManager
,用它的方法进行认证
authenticationManager.authenticate()
1 2 3 4 5
| @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }
|
安全过滤器链配置方法HttpSecurity http
配置方法
默认配置
1 2 3 4
| @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); }
|
super.configure(http);
使用了父类中一些默认配置。查看源代码
1 2 3 4 5 6 7
| protected void configure(HttpSecurity http) throws Exception { ((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.authorizeRequests().anyRequest()).authenticated() .and()). formLogin() .and()) .httpBasic(); }
|
http.authorizeRequests().anyRequest().authenticated()
表示对任何请求都要进行权限认证
http.formLogin()
,加入了UsernamePasswordAuthenticationFilter
过滤器。
默认配置:
- 所有的请求访问都需要被授权。
- 使用 form 表单进行登陆(默认路径为/login),也就是前几篇我们见到的登录页。
- 防止
CSRF
攻击、XSS
攻击。
- 启用 HTTP Basic 认证
自定义配置
关闭防止csrf
攻击
为什么要关闭防止csrf
攻击?
CSRF
是指跨站请求伪造(Cross-site request forgery),是web常见的攻击之一。
https://blog.csdn.net/freeking101/article/details/86537087
SpringSecurity
去防止CSRF
攻击的方式就是通过csrf_token
。后端会生成一个csrf_token
,前端发起请求的时候需要携带这个csrf_token
,后端会有过滤器进行校验,如果没有携带或者是伪造的就不允许访问。
但是在前后端分离的项目中我们的认证信息其实是token,而token并不是存储中cookie中,并且需要前端代码去把token设置到请求头中才可以,所以CSRF
攻击也就不用担心了。
因此使用token是天然防止csrf
攻击的。
不通过Session
获取SecurityContext
1
| http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
权限配置
1 2
| http.authorizeRequests().antMatchers("/user/login").anonymous() .anyRequest().authenticated();
|
对于登录接口 允许匿名访问除上面外的所有请求全部需要鉴权认证
参考链接:
https://blog.csdn.net/qq_41865652/article/details/123685248
https://blog.csdn.net/Shair911/article/details/104181917/
http.authorizeRequests()
主要是对url
进行访问权限控制,通过这个方法来实现url
授权操作。
anyRequest()
,表示匹配所有的url
请求
1 2 3
| http.authorizeRequests() .anyRequest().authenticated();
|
antMatcher(String regx)
,传递一个ant
表达式参数,表示匹配所有满足ant
表达式的请求
ant表达式中特殊字符解释
规则 |
解释说明 |
? |
匹配一个字符 |
* |
匹配0个或多个字符 |
** |
匹配0个或多个目录 |
配置类代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| http.authorizeRequests() .antMatchers("/showLogin", "/errPage").anonymous() .antMatchers( "/css/**", "/js/**", "/images/**", "/fonts/**", "/favicon.ico" ).anonymous() .anyRequest().authenticated();
|
antMatcher(HttpMethod.*, String regx)
,传递一个请求方法类型参数加ant表达式参数,表示匹配所有满足ant表达式的指定请求方式的url
请求方式的枚举类如下:

配置类代码示例:
1 2 3
| http.authorizeRequests() .antMatchers(HttpMethod.GET, "/showLogin", "/errPage").anonymous();
|
访问控制方法
方法名称 |
方法作用 |
permitAll() |
表示所匹配的URL任何人都允许访问 |
anonymous() |
表示可以匿名访问匹配的URL。和permitAll() 效果类似,只是设置为anonymous() 的url会执行filterChain 中的filter |
denyAll() |
表示所匹配的URL都不允许被访问。 |
authenticated() |
表示所匹配的URL都需要被认证才能访问 |
rememberMe() |
允许通过remember-me登录的用户访问 |
access() |
SpringEl 表达式结果为true时可以访问 |
fullyAuthenticated() |
用户完全认证可以访问(非remember-me下自动登录) |
hasRole() |
如果有参数,参数表示角色,则其角色可以访问 |
hasAnyRole() |
如果有参数,参数表示角色,则其中任何一个角色可以访问 |
hasAuthority() |
如果有参数,参数表示权限,则其权限可以访问 |
hasAnyAuthority() |
如果有参数,参数表示权限,则其中任何一个权限可以访问 |
hasIpAddress() |
如果有参数,参数表示IP 地址,如果用户IP 和参数匹配,则可以访问 |
配置案例示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| http.authorizeRequests().antMatchers("/index").permitAll(); http.authorizeRequests().antMatchers("/index").access("permitAll");]
http.authorizeRequests().antMatchers("/home").denyAll(); http.authorizeRequests().antMatchers("/home").access("denyAll");
http.authorizeRequests().antMatchers("/admin").authenticated(); http.authorizeRequests().antMatchers("/admin").access("authenticated");
http.authorizeRequests().antMatchers("/admin").fullyAuthenticated(); http.authorizeRequests().antMatchers("/admin").access("fullyAuthenticated");
http.authorizeRequests().antMatchers("/admin").rememberMe(); http.authorizeRequests().antMatchers("/admin").access("rememberMe");
http.authorizeRequests().antMatchers("/admin").anonymous(); http.authorizeRequests().antMatchers("/admin").access("anonymous");
http.authorizeRequests().antMatchers("/index").hasAuthority("user"); http.authorizeRequests().antMatchers("/index").access("hasAuthority('user')");
http.authorizeRequests().antMatchers("/home").hasAnyAuthority("update", "delete", "insert"); http.authorizeRequests().antMatchers("/home").access("hasAnyAuthority('update','delete','insert')");
http.authorizeRequests().antMatchers("/index").hasRole("GUEST"); http.authorizeRequests().antMatchers("/index").access("hasRole('GUEST')"); http.authorizeRequests().antMatchers("/admin").hasAuthority("ROLE_GUEST"); http.authorizeRequests().antMatchers("/home").hasAnyRole("GUEST", "USER", "ADMIN"); http.authorizeRequests().antMatchers("/home").access("hasAnyRole('ROLE_GUEST','ROLE_USER','ROLE_ADMIN')");
|
添加过滤器到过滤器链
先将获取过滤器
1 2
| @Autowired private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
|
然后配置到过滤器链中
1 2
| http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
addFilterBefore()
:将过滤器放到 **过滤器之前。
addFilter()
:将过滤器放到过滤器链最后。
addFilterAfter()
:将过滤器放到 **过滤器之后。
1 2
| http.addFilterAfter(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
addFilterAt
:将过滤器放在**过滤的位置。并不是取代。
配置异常处理器
先获取异常处理器
1 2 3 4 5
| @Autowired private AccessDeniedHandler accessDeniedHandler;
@Autowired private AuthenticationEntryPoint authenticationEntryPoint;
|
然后进行配置。
1 2
| http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler);
|
表单登录配置
取消默认的自带的表单登录配置
1
| http.formLogin().disable();
|
配置演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @SpringBootConfiguration public class SecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http .formLogin() .loginPage("/login/auth").permitAll() .failureUrl("/login/fail") .defaultSuccessUrl("/login/success",true) .loginProcessingUrl("/login") .usernameParameter("username") .passwordParameter("password") .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/login/logout").permitAll() .deleteCookies("myCookie") .and() .csrf().disable(); } }
|
使用formLogin()
就会添加如下过滤器
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
添加认证成功处理器和认证失败处理器
先获取认证成功处理器和认证失败处理器。
1 2 3 4 5
| @Autowired private AuthenticationSuccessHandler successHandler;
@Autowired private AuthenticationFailureHandler failureHandler;
|
然后再进行配置
1 2 3 4 5
| http.formLogin()
.successHandler(successHandler)
.failureHandler(failureHandler);
|
总的配置代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Autowired private AccessDeniedHandler accessDeniedHandler;
@Autowired private AuthenticationEntryPoint authenticationEntryPoint;
@Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); }
@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }
@Override protected void configure(HttpSecurity http) throws Exception {
http .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/user/login").anonymous() .anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler);
http.authorizeRequests().antMatchers().hasAuthority("system:test:index");
} }
|
__END__