SpringSecurity配置类
在学习这门课的时候,实现各种功能时进行了各种配置。我想将各种配置综合讲述一下。
首先自定义配置类,需要继承WebSecurityConfigurerAdapter
这个类。
在这个类里面做了一些默认配置。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
....
}
自定义密码的加密方式:
更改PasswordEncoder
的实现为BCryptPasswordEncoder
。
/**
* 配置用户密码加密方式
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(); // 这里使用 BCrypt (也可换别的)
}
注入Security工作图中的第二步–>用于验证JWT
在接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要在SecurityConfig中配置把AuthenticationManager注入容器。
注入AuthenticationManager
,用它的方法进行认证
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
使用时:
authenticationManager.authenticate()
安全过滤器链配置方法HttpSecurity http
配置方法
默认配置
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
super.configure(http);
使用了父类中一些默认配置。查看源代码
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
http.csrf().disable()
为什么要关闭防止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
//不通过Session获取SecurityContext
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
1. 权限配置
参考链接:
https://blog.csdn.net/qq_41865652/article/details/123685248
https://blog.csdn.net/Shair911/article/details/104181917/
http.authorizeRequests()
主要是对url
进行访问权限控制,通过这个方法来实现url
授权操作。
http.authorizeRequests()也支持连缀写法,总体公式为:
url 匹配规则. 权限控制方法
1. anyRequest()
2. antMatcher()
3. regexMatchers()
4. mvcMatchers()
-
mvcMatchers()
适用于配置了 servletPath 的情况。
servletPath 就是所有的 URL 的统一前缀。在 SpringBoot 整合SpringMVC 的项目中可以在 application.properties 中添加下面内容设置 ServletPath
spring.mvc.servlet.path=/bjsxt
在 Spring Security 的配置类中配置.servletPath()是 mvcMatchers()返回值特有的方法,antMatchers()和 regexMatchers()没有这个方法。在 servletPath()中配置了 servletPath 后,mvcMatchers()直接写 SpringMVC 中@RequestMapping()中设置的路径即可。
http.authorizeRequests()
.mvcMatchers("demo").servletPath("/bjsxt").permitAll()
如果不习惯使用 mvcMatchers()也可以使用 antMatchers(),下面代码和上面代码是等效的
http.authorizeRequests()
.antMatchers( "/bjsxt/demo").permitAll()
2. 访问控制方法
方法名称 |
方法作用 |
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 和参数匹配,则可以访问 |
配置案例示例:
//任何用户都可以访问
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')");
//spring security中的role并非是一个或多个权限的集合,而是权限的一种,通常以ROLE_开头
//role就是ROLE_开头的权限
//注意:hasRole、hasAnyRole里面的role不需要以ROLE_开头,否则会报异常
//注意:如果在access里面使用hasRole、hasAnyRole则ROLE_前缀可加,可不加
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')");
添加过滤器到过滤器链
-
先将获取过滤器
@Autowired
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; // 注入Jwt认证过滤器
-
然后配置到过滤器链中
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
//将jwtAuthenticationTokenFilter 过滤器放到UsernamePasswordAuthenticationFilter过滤器前。
-
addFilterBefore()
:将过滤器放到 **过滤器之前。
-
addFilter()
:将过滤器放到过滤器链最后。
-
addFilterAfter()
:将过滤器放到 **过滤器之后。
http.addFilterAfter(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
//将jwtAuthenticationTokenFilter 过滤器放到UsernamePasswordAuthenticationFilter过滤器后。
-
addFilterAt
:将过滤器放在**过滤的位置。并不是取代。
配置异常处理器
-
先获取异常处理器
@Autowired
AuthenticationEntryPoint authenticationEntryPoint; // 注入(自定义的 认证过程中 出现异常的处理方法)
@Autowired
AccessDeniedHandler accessDeniedHandler; // 注入(自定义 授权过程中 出现异常的处理方法)
-
然后进行配置。
/**
* 配置异常处理器
*/
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint) // 配置认证失败处理器
.accessDeniedHandler(accessDeniedHandler); // 配置授权失败处理器
表单登录配置
取消默认的自带的表单登录配置
http.formLogin().disable();
配置演示
@SpringBootConfiguration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()//开启formLogin默认配置
.loginPage("/login/auth").permitAll()//请求时未登录跳转接口
.failureUrl("/login/fail")//用户密码错误跳转接口
.defaultSuccessUrl("/login/success",true)//登录成功跳转接口
.loginProcessingUrl("/login")//post登录接口,登录验证由系统实现
.usernameParameter("username") //要认证的用户参数名,默认username
.passwordParameter("password") //要认证的密码参数名,默认password
.and()
.logout()//配置注销
.logoutUrl("/logout")//注销接口
.logoutSuccessUrl("/login/logout").permitAll()//注销成功跳转接口
.deleteCookies("myCookie") //删除自定义的cookie
.and()
.csrf().disable(); //禁用csrf
}
}
使用formLogin()
就会添加如下过滤器
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
添加认证成功处理器和认证失败处理器
先获取认证成功处理器和认证失败处理器。
@Autowired
private AuthenticationSuccessHandler successHandler;
@Autowired
private AuthenticationFailureHandler failureHandler;
然后再进行配置
http.formLogin()
//配置认证成功处理器
.successHandler(successHandler)
//配置认证失败处理器
.failureHandler(failureHandler);
总的配置代码
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启SecurityConfig 权限控制功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Autowired
AuthenticationEntryPoint authenticationEntryPoint;
@Autowired
AccessDeniedHandler accessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//前后端分离的项目需要关闭csrf
.csrf().disable()
//不通过Session获取SecurityContext
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// 对于登录接口 允许匿名访问
.antMatchers("/user/login").anonymous()
// 除上面外的所有请求全部都需要认证即可访问
.anyRequest().authenticated();
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint) // 配置认证失败处理器
.accessDeniedHandler(accessDeniedHandler); // 配置授权失败处理器
//关闭默认的注销功能
http.logout().disable();
//把token校验过滤器添加到过滤器链中
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 允许跨域
http.cors();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 配置用户密码加密方式
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(); // 这里使用 BCrypt (也可换别的)
}
}