【发布时间】:2020-09-11 04:09:59
【问题描述】:
我正在使用 Spring Boot 和 Spring Security 创建具有 JWT 令牌基础安全性的 rest API。我想在令牌无效时抛出自定义异常。这样我就创建了自定义异常类,并且每当我抛出该异常时,每次都会在邮递员中得到空白响应。
我想扔这个
if (header == null || !header.startsWith("Bearer")) {
throw new JwtTokenMissingException("No JWT token found in the request headers");
}
因为我发送的令牌没有 Bearer 关键字。它在控制台中打印,但不在邮递员中。
邮递员每次都回复空白
JwtAuthenticationEntryPoint 类
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable[!
private static final long serialVersionUID = 1L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
WebSecurityConfig 类
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
}
@Bean
public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/login").permitAll().anyRequest()
.authenticated().and().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
JwtAuthenticationFilter 类
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwtTokenPrefix}")
private String tokenPrefix;
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
String header = req.getHeader("Authorization");
String username = null;
String authToken = null;
if (header == null || !header.startsWith("Bearer")) {
throw new JwtTokenMissingException("No JWT token found in the request headers");
}
authToken = header.replace(tokenPrefix, "");
jwtTokenUtil.validateJwtToken(authToken);
username = jwtTokenUtil.getUserNameFromJwtToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(req));
logger.info("authenticated user " + username + ", setting security context");
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(req, res);
}
}
JwtTokenUtil 类
@Component
public class JwtTokenUtil implements Serializable {
private static final long serialVersionUID = 1L;
@Value("${jwtSecret}")
private String jwtSecret;
@Value("${jwtExpirationInMs}")
private int jwtExpirationMs;
public String generateJwtToken(String username) {
return Jwts.builder()
.setSubject((username))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
}
public void validateJwtToken(String authToken) throws JwtTokenMalformedException, JwtTokenMissingException {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
} catch (SignatureException e) {
throw new JwtTokenMalformedException("Invalid JWT signature");
} catch (MalformedJwtException e) {
throw new JwtTokenMalformedException("Invalid JWT token");
} catch (ExpiredJwtException e) {
throw new JwtTokenMalformedException("Expired JWT token");
} catch (UnsupportedJwtException e) {
throw new JwtTokenMalformedException("Unsupported JWT token");
} catch (IllegalArgumentException e) {
throw new JwtTokenMissingException("JWT claims string is empty.");
}
}
}
自定义异常类
public class JwtTokenMalformedException extends AuthenticationException {
private static final long serialVersionUID = 1L;
public JwtTokenMalformedException(String msg) {
super(msg);
}
}
public class JwtTokenMissingException extends AuthenticationException {
private static final long serialVersionUID = 1L;
public JwtTokenMissingException(String msg) {
super(msg);
}
}
【问题讨论】:
-
如果你想在响应体中看到一些东西,那么你应该在处理异常时在响应体中写一些东西。请参考此页面:docs.oracle.com/javaee/6/api/javax/servlet/http/…。当您的消息被忽略时,您可能会遇到这种情况。
-
是的,它的工作。在响应正文中更改了一些代码之后它工作正常
标签: java spring-boot exception spring-security