如何解决无法获取刷新令牌并取回响应
在这个项目中,我刚刚添加了一个用户实体和角色实体,并添加了 jwt auth,在 jwt 到期之前,一切正常。添加过滤器和入口点后,我收到入口点引发的错误:
{
"error": "Full authentication is required to access this resource"
}
在 JwtRequest 过滤器中,我添加了一个 try catch 来捕获 ExpiredJwtException,但我仍然无法刷新令牌并获得请求的端点的响应。
/* Intercepts every request and examine the header for jwt */
@Component
public class JwtRequestFilter extends OncePerRequestFilter
{
@Autowired
private AuthService authService;
@Autowired
private RestTemplate restTemplate;
@Autowired
private JwtUtil jwtUtil;
private static final String REFRESH_TOKEN = "http://localhost:8080/refreshtoken";
private static final String AUTHENTICATION_URL = "http://localhost:8080/authenticate";
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException,IOException
{
try {
/*Get only the token */
String jwt = extractJwtFromRequest(request);
if(StringUtils.hasText(jwt) && this.jwtUtil.validateToken(jwt))
{
System.out.println("Entro," +jwt);
UserDetails userDetails = this.authService.refreshTokenUserDetails(this.jwtUtil.getUsernameFromToken(jwt));
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
/* After setting the auth in the context,we specify that the current user is authenticated..
* So it passes the Spring Security Config successfully */
SecurityContextHolder.getContext().setAuthentication(authToken);
} else {
System.out.println("Cannot set the Security Context");
}
} catch (ExpiredJwtException ex) {
/* Expired token */
if (ex.getMessage().contains("io.jsonwebtoken.ExpiredJwtException"))
{
request.setAttribute("claims",ex.getClaims());
/* Refresh token*/
String jwt = this.refreshToken(extractJwtFromRequest(request));
request.setAttribute("Autorization",jwt);
Object[] res = this.getData(request,jwt);
byte[] body = new ObjectMapper().writeValueAsBytes(res);
response.getOutputStream().write(body);
}
} catch (BadCredentialsException ex) {
request.setAttribute("exception",ex);
throw ex;
} catch (Exception e) {
System.out.println(e);
throw e;
}
filterChain.doFilter(request,response);
}
private String getData(HttpServletRequest request,String token)
{
String response = null;
HttpHeaders headers = getHeaders();
headers.set("Authorization",token);
headers.set("isRefreshToken","true");
HttpEntity<String> jwtEntity = new HttpEntity<String>(headers);
/* Use token to get response */
String urlRequested = request.getRequestURL().toString();
ResponseEntity<String> requested = restTemplate.exchange(urlRequested,HttpMethod.GET,jwtEntity,String.class);
if(requested.getStatusCode().equals(HttpStatus.OK))
{
response = requested.getBody();
}
return response;
}
private HttpHeaders getHeaders()
{
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type",MediaType.APPLICATION_JSON_VALUE);
headers.set("Accept",MediaType.APPLICATION_JSON_VALUE);
return headers;
}
private String extractJwtFromRequest(HttpServletRequest request)
{
String authorizationHeader = request.getHeader("Authorization");
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
return authorizationHeader.substring(7);
}
return null;
}
private String refreshToken(String token)
{
HttpHeaders headers = getHeaders();
headers.set("Authorization","true");
HttpEntity<String> jwtEntity = new HttpEntity<String>(headers);
/* Use Token to get Response */
ResponseEntity<AuthResponse> refreshTokenResponse = restTemplate.exchange(REFRESH_TOKEN,AuthResponse.class);
if(refreshTokenResponse.getStatusCode().equals(HttpStatus.OK))
{
return "Bearer " + refreshTokenResponse.getBody().getJwt();
}
return null;
}
private void allowForRefreshToken(ExpiredJwtException ex,HttpServletRequest request)
{
/* Create a UsernameAuthenticationToken with null values */
UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(null,null);
/* After setting the auth in the context,we specify that the current user is authenticated. So it
* passes the Spring Security Config successfully */
SecurityContextHolder.getContext().setAuthentication(upat);
/* Set the claims so that in controller we will be using it to create new Jwt */
request.setAttribute("claims",ex.getClaims());
}
}
JwtAuthenticationEntryPoint
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint
{
@Override
public void commence(HttpServletRequest request,AuthenticationException authException) throws IOException,ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message;
/* Check if the request as any exception that we have stored in Request */
final Exception exception = (Exception) request.getAttribute("exception");
// If yes then use it to create the response message else use the authException
if (exception != null)
{
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("cause",exception.toString()));
response.getOutputStream().write(body);
} else {
if (authException.getCause() != null) {
message = authException.getCause().toString() + " " + authException.getMessage();
} else {
message = authException.getMessage();
}
/* Error on postman */
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error",message));
response.getOutputStream().write(body);
}
}
}
SessionController 端点
@RequestMapping(value = "/refresh-token",method = RequestMethod.GET)
public ResponseEntity<?> refreshToekn(HttpServletRequest request) throws Exception {
/* From the http ruest get claims */
DefaultClaims claims = (io.jsonwebtoken.impl.DefaultClaims) request.getAttribute("claims");
Map<String,Object> expectedMap = this.authService.getMapFromIoJsonwebtokenClaims(claims);
String token = this.authService.refreshToken(expectedMap,expectedMap.get("sub").toString());
return ResponseEntity.ok(new AuthResponse(token));
}
身份验证服务
public String refreshToken(Map<String,Object> claims,String subject)
{
return this.jwtUtil.createTokenInfinity(claims,subject);
}
public Map<String,Object> getMapFromIoJsonwebtokenClaims(Claims claims)
{
Map<String,Object> expectedMap = new HashMap<String,Object>();
for (Map.Entry<String,Object> entry : claims.entrySet())
{
expectedMap.put(entry.getKey(),entry.getValue());
}
return expectedMap;
}
最后是 JwtUtil
public String createTokenInfinity(Map<String,String subject)
{
/* Subject -> person who has been authenticated */
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + REFRESH_TIME)) //* 60 *60 *800)
.signWith(SignatureAlgorithm.HS256,SECRET_KEY).compact();
}
如果你能告诉我一个更好的方法来完成这项工作,那将非常有帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。