带有 spring-boot 和 spring-security 的 JWT
Posted
技术标签:
【中文标题】带有 spring-boot 和 spring-security 的 JWT【英文标题】:JWT with spring-boot and spring-security 【发布时间】:2018-01-29 22:33:36 【问题描述】:我对 Spring-Security 非常陌生。我正在尝试在我的spring-boot
应用程序中实现JWT
以执行authentication
。我跟着示例代码,我能够生成jwt
。但是根据示例文件中的配置,我可以使用配置中的内存数据集验证HttpRequest
中的输入。但是,我不明白如何检查request
中发送的username
和password
以及我的database
中存在的值。请指导我。我的配置类是
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in header
.addFilterBefore(new JWTAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
// Create a default account
auth.inMemoryAuthentication()
.withUser("admin")
.password("password")
.roles("ADMIN");
在被覆盖的configure(AuthenticationManagerBuilder auth) throws Exception
中,我可以设置凭据,该凭据将与request
中存在的凭据进行比较/login
路径
public class TokenAuthenticationService
static final long EXPIRATIONTIME = 864_000_000; // 10 days
static final String SECRET = "ThisIsASecret";
static final String TOKEN_PREFIX = "Bearer";
static final String HEADER_STRING = "Authorization";
static void addAuthentication(HttpServletResponse res, String username)
String JWT = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
static Authentication getAuthentication(HttpServletRequest request)
String token = request.getHeader(HEADER_STRING);
if (token != null)
// parse the token.
String user = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();
return user != null ?
new UsernamePasswordAuthenticationToken(user, null, Collections.emptyList()) :
null;
return null;
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter
public JWTLoginFilter(String url, AuthenticationManager authManager)
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authManager);
@Override
public Authentication attemptAuthentication(
HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException, IOException, ServletException
AccountCredentials creds = new ObjectMapper()
.readValue(req.getInputStream(), AccountCredentials.class);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
Collections.emptyList()
)
);
@Override
protected void successfulAuthentication(
HttpServletRequest req,
HttpServletResponse res, FilterChain chain,
Authentication auth) throws IOException, ServletException
TokenAuthenticationService
.addAuthentication(res, auth.getName());
public class JWTAuthenticationFilter extends GenericFilterBean
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException
Authentication authentication = TokenAuthenticationService
.getAuthentication((HttpServletRequest)request);
SecurityContextHolder.getContext()
.setAuthentication(authentication);
filterChain.doFilter(request,response);
【问题讨论】:
【参考方案1】:您需要实现 UserDetailsService 接口(访问您的数据库)并配置它以供 Spring Security 使用。
一个很好的例子(没有 JWT,但这不是重点)可以在这里找到:Spring Security: Authentication with a Database-backed UserDetailsService
【讨论】:
以上是关于带有 spring-boot 和 spring-security 的 JWT的主要内容,如果未能解决你的问题,请参考以下文章
带有 spring-boot 和 spring-security 的 JWT
带有 pom.xml 和 app.java 的简单 spring-boot 应用程序显示构建失败错误
如何使用带有 gradle 的多个嵌入式服务器运行 spring-boot 集成测试