【发布时间】:2018-11-18 07:59:03
【问题描述】:
我在班级WebSecurity extends WebSecurityConfigurerAdapter 中有此安全设置:
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.addFilterBefore(corsFilter(), SessionManagementFilter.class)
.csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()));
}
JWTAuthenticationFilter:
class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter
{
private AuthenticationManager authenticationManager;
private Logger logger = Logger.getLogger("JWTAuthenticationFilter");
JWTAuthenticationFilter(AuthenticationManager authenticationManager)
{
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException
{
String username = req.getParameter("username");
logger.info("Login attempt with username: " + username);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, req.getParameter("password"), new ArrayList<>())
);
}
@Override
protected void successfulAuthentication(
HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth
)
{
String token = Jwts
.builder()
.setSubject(((User) auth.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
}
}
JWTAuthorizationFilter:
public class JWTAuthorizationFilter extends BasicAuthenticationFilter
{
JWTAuthorizationFilter(AuthenticationManager authManager)
{
super(authManager);
}
@Override
protected void doFilterInternal(
HttpServletRequest req,
HttpServletResponse res,
FilterChain chain
) throws IOException, ServletException
{
String header = req.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(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(HEADER_STRING);
if (token != null)
{
String user = Jwts
.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();
if (user != null)
{
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
- 当我发送 Authorization: Bearer “正确令牌”标头时,它工作正常。
- 当我发送 Authorization: Bearer "expired token" 标头时,我收到了正确的错误消息。
- 但如果我不发送标头,它不会阻塞 API 调用,并且我得到的响应没有错误消息。
- 如果我发送带有随机文本而不是 Bearer 的 Auth 标头,我会收到没有错误消息的响应。
这有什么问题?
【问题讨论】:
-
JWTAuthenticationFilter是如何实现的。 -
我用代码更新了问题。
-
我没有看到任何与使用令牌进行身份验证相关的内容。那么它怎么能起作用呢?您基本上是使用用户名和密码登录,然后提供令牌。您无处读取此过滤器中的令牌?那么您的令牌在哪里被读取并用于身份验证?
-
再次使用 JWTAuthorizationFilter 类更新,问题可能出在此处。
-
如果我不发送 Authorization 标头,getAuthentication 将不会被触发。
标签: spring spring-boot authentication spring-security jwt