需求:为了保证应用一直用就不会过期,需要每次请求都为token续时长。
简要说明:这里不并讲刷新token的方式,只是把一个token值不丢弃一直续。这里以redis存储、密码模式的token续时长为例。你或许在想redis直接在redis基础上把时长续上不就行了,也行,但需要读源码找到相应的redis_key,最后相当于搬运了部分源码,复用率极低。这里讲的是利用框架提供方法来续时长的方式,下面是我的代码。
方式一:首先想到的是啥,是检查token时续,源码动不了,就用切面附加行为。
@Aspect
@Component
@Slf4j
public class CheckTokenAop {
@Autowired
private TokenStore tokenStore;
@Autowired
private AuthenticationManager authenticationManager;
// token时长:秒
private int renewalInterval = 1800;
// authToken切入点
@Pointcut("execution(public * org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.checkToken(..))")
public void checkTokenPointCut() {
}
/**
* @usage 为token续时长
* @author kbz_meng
* @date 2019年7月12日 下午6:22:08
*/
@AfterReturning("checkTokenPointCut()")
public void refreshToken(JoinPoint point) {
String token = String.valueOf(point.getArgs()[0]);
OAuth2AccessToken accessToken = tokenStore.readAccessToken(token);
// 不允许null
if (accessToken == null) {
return;
}
int duration = renewalInterval * 1000;
//其它登录信息也同步刷新
if (accessToken instanceof DefaultOAuth2AccessToken) {
DefaultOAuth2AccessToken defaultAccessToken = (DefaultOAuth2AccessToken) accessToken;
defaultAccessToken.setExpiration(new Date(System.currentTimeMillis() + duration));
}
OAuth2Authentication authentication = tokenStore.readAuthentication(accessToken);
tokenStore.storeAccessToken(accessToken, authentication);
log.debug("refresh token expiration :{} +++++", token);
}
}
方式二:然后想到的是过滤器,验证token有Fileter吧,验通过后,就可以续了。
@Slf4j
@Component
public class RefreshTokenFilter implements Filter {
@Autowired
private TokenStore tokenStore;
// token时长:秒
private int renewalInterval = 1800;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
String token = SecurityUtils.getToken();
if (StringUtils.isEmpty(token)) {
filterChain.doFilter(servletRequest,servletResponse);
return;
}
OAuth2AccessToken accessToken = tokenStore.readAccessToken(token);
// 不允许null
if (accessToken == null) {
filterChain.doFilter(servletRequest,servletResponse);
return;
}
int duration = renewalInterval * 1000;
//其它登录信息也同步刷新
if (accessToken instanceof DefaultOAuth2AccessToken) {
DefaultOAuth2AccessToken defaultAccessToken = (DefaultOAuth2AccessToken) accessToken;
defaultAccessToken.setExpiration(new Date(System.currentTimeMillis() + duration));
OAuth2Authentication authentication = tokenStore.readAuthentication(accessToken);
tokenStore.storeAccessToken(accessToken, authentication);
log.debug("refresh token expiration :{} +++++", token);
}
filterChain.doFilter(servletRequest,servletResponse);
}
}
然后把刷新token的Fileter加到正确位置
public class OAuth2WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private RefreshTokenFilter refreshTokenFilter;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// token续时长
.addFilterAfter(refreshTokenFilter, FilterSecurityInterceptor.class)
//....其它设置
.csrf().disable();
}
}