java - 如何在 Spring Boot 中从旧令牌生成新的 JWT 令牌?
问题描述
我正在这样WebSecurityConfigurerAdapter
使用
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailServiceImpl userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
private ApplicationUserRepository applicationUserRepository;
public WebSecurity(UserDetailServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder, ApplicationUserRepository applicationUserRepository) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.applicationUserRepository = applicationUserRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint());
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(""/configuration/ui",
"/configuration/security"
"/webjars/**", "/users/social-sign-up", "client/**","/actuator/**",
"/instances","/assets/**","/home","/tables","/resources/**","/static/**",
"/css/**","/js/**","/scss/**","/templates").permitAll()
.antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_VERIFY_URL).permitAll()
.antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL).permitAll().anyRequest().authenticated()
.and().addFilter(new JWTAuthenticationFilter(authenticationManager(), applicationUserRepository))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
然后我有一个BasicAuthenticationFilter
这样的
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authManager) {
super(authManager);
}
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
String header = req.getHeader(SecurityConstants.HEADER_STRING);
if (header == null || !header.startsWith(SecurityConstants.TOKEN_PREFIX)) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(SecurityConstants.HEADER_STRING);
if (token != null) {
// parse the token.
String user = JWT.require(Algorithm.HMAC512(SecurityConstants.SECRET.getBytes())).build()
.verify(token.replace(SecurityConstants.TOKEN_PREFIX, "")).getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
然后我有UsernamePasswordAuthenticationFilter
这样的
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
private ApplicationUserRepository applicationUserRepository;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager,ApplicationUserRepository applicationUserRepository) {
this.authenticationManager = authenticationManager;
this.applicationUserRepository = applicationUserRepository;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException {
try {
ApplicationUser creds = new ObjectMapper().readValue(req.getInputStream(), ApplicationUser.class);
System.err.println("Creds " + creds.getUsername() + ", " + creds.getPassword());
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(),
creds.getPassword(), new ArrayList<>()));
} catch (Exception e) {
// e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
Authentication auth) throws IOException, ServletException {
String token = JWT.create().withSubject(((User) auth.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).sign(HMAC512(SECRET.getBytes()));
res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
res.setStatus(HttpServletResponse.SC_OK);
String userName = ((User)auth.getPrincipal()).getUsername();
ApplicationUser au= applicationUserRepository.findByUsername(userName);
String json = new ObjectMapper().writeValueAsString(au);
res.getWriter().write(json);
res.getWriter().flush();
res.getWriter().close();
}
}
我能够在 HEADER 中生成 JWT 令牌。像这样
Authorization →Bearer awgaagarbrqe342tewrbwrewh.23tebvre34h4wbseb43qberqbqv.23gwrwvw4hw5445jmet76e-gqgqggq323t9003qgnibqp2389bvqp9q83bv9
我想要实现的是,每当令牌过期时,发送最新过期令牌的客户端将根据他们发送的令牌获得一个新令牌。所以我的问题是,我如何生成一个刷新令牌或一种将旧的过期令牌并生成一个新令牌的机制?
解决方案
这样做会削弱应用程序的安全性,因为可以从过期的令牌(无效令牌)中检索新令牌。所以你应该尽量不要这样做。
如果必须这样做,请在数据库中保留一个包含令牌及其有效性的表,然后当您收到无效的 jwt 令牌异常时,请转到数据库检查所述令牌并查看它何时过期。如果是 5 分钟前,那么你可能会更新它,否则不要。
推荐阅读
- javascript - 角度材质对话框发射器
- autodesk-forge - 获取属性端点中缺少某些属性
- oracle - PL/SQL 的执行流程
- iot - 我们在哪里可以看到 zigbee call fow 中传感器的心跳?
- ruby-on-rails - 电子邮件中的 Sendgrid 链接产生您的连接不是浏览器中的私人错误
- sql - 选择案例中的错误
- javascript - 角度表 - 调整性能不佳的大型表
- batch-file - 如何在批处理脚本的 FOR 循环中寻址元素 i+1?
- ignite - Apache Ignite 数据区域行为
- unity3d - 为什么我的 ClientScene.RegisterSpawnHandler 不起作用?