登录框架#
使用的spring security框架,通过过滤器进行拦截,
登录的时候通过jwt生成token
调用接口,携带token,同时刷新token时长
除了登录接口及 swagger,其他的都进行拦截
过滤器#
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
| @Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String[] EXCLUDE_URL = {"/doc.html","/login"};
/**
* 认证失败处理类
*/
private final AuthenticationEntryPointImpl unauthorizedHandler;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final JwtAppletTokenUtils jwtUtil;
public WebSecurityConfig(AuthenticationEntryPointImpl unauthorizedHandler, JwtAccessDeniedHandler jwtAccessDeniedHandler, JwtAppletTokenUtils jwtUtil) {
this.unauthorizedHandler = unauthorizedHandler;
this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
this.jwtUtil = jwtUtil;
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// CSRF禁用,因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).accessDeniedHandler(jwtAccessDeniedHandler)
// 防止iframe 造成跨域(这一段不写会导致swagger访问不了)
.and().headers().frameOptions().disable().and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 放行OPTIONS请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 允许匿名访问接口
.antMatchers(EXCLUDE_URL).permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
httpSecurity.apply(new TokenConfigurer(jwtUtil));
}
/***
* 核心过滤器配置方法
* @param web
*/
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/doc.html", "/webjars/**", "/**/api-docs/**","/login","/pay/callback","/pay/refundCallback","/pay/callback");
}
static class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final JwtAppletTokenUtils jwtUtil;
public TokenConfigurer(JwtAppletTokenUtils jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
public void configure(HttpSecurity http) {
JwtAuthenticationTokenFilter beforeFilter = new JwtAuthenticationTokenFilter(jwtUtil);
http.addFilterBefore(beforeFilter, UsernamePasswordAuthenticationFilter.class);
}
}
}
|
Jwt 生成方法:#
1
2
3
| public String createToken(Map<String, Object> claims) {
return Jwts.builder().claim(AUTHORITIES_KEY, JSONObject.toJSONString(claims)).setId(UUID.randomUUID().toString()).setIssuedAt(new Date()).setExpiration(new Date((new Date()).getTime() + tokenValidityInSeconds*1000)).compressWith(CompressionCodecs.DEFLATE).signWith(key, SignatureAlgorithm.HS512).compact();
}
|
Jwt 校验方法:#
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
| public boolean validateToken(String authToken) {
try {
Date expiration = getExpirationDateFromToken(authToken);
if (ObjectUtil.isNotNull(expiration) && expiration.getTime() - System.currentTimeMillis() <= LAST_EXPIRE_TIME) {
// 刷新过期时间
Claims claims = getClaimsFromToken(authToken);
claims.setExpiration(new Date((new Date()).getTime() + tokenValidityInSeconds*1000));
}
return true;
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
log.error("Invalid JWT signature.", e);
} catch (ExpiredJwtException e) {
log.error("Expired JWT token.", e);
} catch (UnsupportedJwtException e) {
log.error("Unsupported JWT token.", e);
} catch (IllegalArgumentException e) {
log.error("JWT token compact of handler are invalid.", e);
}
return false;
}
public Date getExpirationDateFromToken(String token) {
Date expiration;
try {
final Claims claims = getClaimsFromToken(token);
expiration = claims.getExpiration();
} catch (Exception e) {
expiration = null;
}
return expiration;
}
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
|