SpringSecurity的配置和实现是比较复杂的,本文在经过一系列的优化和改造后,实现了比较灵活的安全权限控制。
下面直接上代码讲解。
pom引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
项目中的application.xml
jwt:
tokenHeader: token #JWT存储的请求头
secret: mall #JWT加解密使用的密钥
expiration: 604800 #JWT的超期限时间(60*60*24*7)
secure:
ignored:
urls: #安全路径白名单(不验证token)
- /swagger-ui.html
- /swagger-resources/**
- /swagger/**
- /**/v2/api-docs
- /img/**
- /**/*.js
- /**/*.css
- /**/*.png
- /**/*.ico
- /**/*.json
- /webjars/springfox-swagger-ui/**
- /actuator/**
- /druid/**
- /api/member/login
noTokenUrls: #允许无token访问的地址(有token进行验证,无token放行)
- /api/home/**
核心config
/**
* 对SpringSecurity的配置的扩展,支持自定义白名单资源路径和查询用户逻辑
*
*/
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity
.authorizeRequests();
//不需要保护的资源路径允许访问
for (String url : ignoreUrlsConfig().getUrls()) {
registry.antMatchers(url).permitAll();
}
//不需要token的资源路径允许访问
ignoreUrlsConfig().getNoTokenUrls().forEach(url -> {
registry.antMatchers(url).permitAll();
});
//允许跨域请求的OPTIONS请求
registry.antMatchers(HttpMethod.OPTIONS)
.permitAll();
// 任何请求需要身份认证
registry.and()
.authorizeRequests()
.anyRequest()
.authenticated()
// 关闭跨站请求防护及不使用session
.and()
.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// 自定义权限拒绝处理类
.and()
.exceptionHandling()
.accessDeniedHandler(restfulAccessDeniedHandler())
.authenticationEntryPoint(restAuthenticationEntryPoint())
// 自定义权限拦截器JWT过滤器
.and()
.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public JwtTokenUtil jwtTokenUtil() {
return new JwtTokenUtil();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
return new JwtAuthenticationTokenFilter();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();