JWT介绍
JWT(JSON Web Token)是一种基于JSON的开放标准(RFC 7519),用于在网络上安全地传输声明(claims)。JWT可以被用于认证和信息交换,通常用于前后端之间的身份验证和授权。
JWT 由三部分组成,分别如下
Header(头部)
包含了JWT的类型(typ)和使用的签名算法(alg)等信息,通常由两部分组成,第一部分是JWT的类型("typ")和使用的签名算法("alg")。如下所示。
{
"typ": "JWT",
"alg": "HS256"
}
上面的示例表示 JWT的类型为 "JWT",使用的签名算法是 HMAC SHA-256(HS256)
Payload(载荷)
包含了需要传输的信息,称为声明(claims),声明可以是标准声明(registered claims)、公共声明(public claims)和私有声明(private claims)。标准声明包括了一些预定义的声明,如下所示。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
上面的示例中,sub表示主题(subject),name表示姓名,admin表示是否是管理员。
Signature(签名)
使用Base64编码的Header和Payload连接在一起,然后加上一个密钥,通过指定的算法生成签名,用于验证消息的完整性和真实性。
JWT主要用于身份认证和授权,用户在登录成功后,服务端会生成一个JWT并返回给客户端,客户端在后续的请求中带上JWT,服务端验证JWT的合法性,如果验证通过则认为用户已经登录。常见的场景包括单点登录(SSO)、跨域认证、微服务架构中的用户身份传递等。
SpringBoot如何整合JWT?
在Spring Boot中整合JWT需要进行以下步骤
- 添加依赖:在pom.xml文件中添加 JWT 相关的依赖。
- 创建 JWT 工具类:编写一个工具类来生成 JWT、解析 JWT 等操作。
- 创建认证过滤器:编写一个认证过滤器,在用户登录成功后生成 JWT,并在请求中验证 JWT 的合法性。
- 配置 Spring Security:配置 Spring Security 来定义用户认证和授权的规则。
添加POM依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
创建工具类
编写一个工具类来生成 JWT、解析 JWT 等操作。
@Component
public class JwtUtils {
private static final String SECRET_KEY = "your-secret-key"; // 用于生成签名的密钥
private static final long EXPIRATION_TIME = 864_000_000; // JWT 有效期为 10 天
public String generateToken(String username) {
Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(key)
.compact();
}
public String getUsernameFromToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(SECRET_KEY.getBytes())
.build()
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(SECRET_KEY.getBytes())
.build()
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}
认证过滤器
编写一个认证过滤器,在用户登录成功后生成 JWT,并在请求中验证 JWT 的合法性。
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
private final JwtUtils jwtUtils;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtUtils jwtUtils) {
this.authenticationManager = authenticationManager;
this.jwtUtils = jwtUtils;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
String username = obtainUsername(request);
String password = obtainPassword(request);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
String username = (String) authResult.getPrincipal();
String token = jwtUtils.generateToken(username);
response.addHeader("Authorization", "Bearer " + token);
}
}
整合SpringSecurity
在Spring Boot配置类中配置Spring Security。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserDetailsServiceImpl userDetailsService;
@Resource
private JwtUtils jwtUtils;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance(); // 不对密码进行加密处理
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/authenticate").permitAll() // 放行登录接口
.anyRequest().authenticated(); // 其他请求需要认证
http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager(), jwtUtils),
UsernamePasswordAuthenticationFilter.class);
}
}
在这个示例中,我们定义了一个简单的SpringBoot应用,并使用了SpringSecurity进行用户认证。JwtAuthenticationFilter继承了SpringSecurity提供的
UsernamePasswordAuthenticationFilter,并在用户登录成功后生成 JWT。
SecurityConfig 类配置了SpringSecurity,定义了用户认证规则,并添加了JwtAuthenticationFilter过滤器来验证JWT的合法性。JwtUtils类则封装了JWT的生成、解析和验证方法。
需要注意的是,在实际项目中,需要根据实际情况来配置用户认证、授权规则,并采用安全的密码加密方式。