JWT(JSON Web Token)

Casual_Lei 2024-07-14 09:33:22 阅读 82

JWT(JSON Web Token)是一种用于在各方之间作为 JSON 对象安全传输信息的开放标准(RFC 7519)。它是自包含的,既可以被验证,也可以被信任,因为它是通过数字签名的。JWT 在许多现代应用中用于身份验证和授权。

JWT 的结构

JWT 由三部分组成:Header(头部)、Payload(负载)、Signature(签名)。每部分使用 Base64Url 编码,并用点号(.)分隔。

Header:

包含令牌类型(JWT)和签名算法(如 HMAC SHA256 或 RSA)。

<code>{

"alg": "HS256",

"typ": "JWT"

}

Payload:

包含声明(claims),即实体(通常是用户)及附加数据。标准声明包括 iss(签发者)、exp(过期时间)、sub(主题)等。

{

"sub": "1234567890",

"name": "John Doe",

"iat": 1516239022

}

Signature:

用于验证令牌的发送方及数据完整性。将编码后的 Header 和 Payload 通过指定算法进行签名。

HMACSHA256(

base64UrlEncode(header) + "." +

base64UrlEncode(payload),

secret)

JWT 的工作流程

客户端登录:用户使用其凭据登录,服务器验证身份后生成 JWT,并将其返回给客户端。客户端存储 JWT:客户端将 JWT 存储在本地存储、cookie 或其他安全位置。客户端请求资源:客户端在每个请求的 HTTP 头部添加 JWT(通常在 Authorization: Bearer <token>)。服务器验证 JWT:服务器验证 JWT 的签名和有效性(如过期时间)。验证通过后,服务器处理请求并返回相应的数据。

Spring Security 与 JWT 集成

Spring Security 提供了与 JWT 集成的强大支持。以下是一个简单的示例,展示如何使用 Spring Security 和 JWT 进行身份验证和授权。

依赖

pom.xml 中添加必要的依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-security</artifactId>

</dependency>

<dependency>

<groupId>io.jsonwebtoken</groupId>

<artifactId>jjwt</artifactId>

<version>0.9.1</version>

</dependency>

配置类

创建一个配置类,配置 Spring Security 和 JWT 验证。

@EnableWebSecurity

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override

protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable()

.authorizeRequests()

.antMatchers("/login").permitAll()

.anyRequest().authenticated()

.and()

.addFilter(new JWTAuthenticationFilter(authenticationManager()))

.addFilter(new JWTAuthorizationFilter(authenticationManager()));

}

@Bean

public BCryptPasswordEncoder bCryptPasswordEncoder() {

return new BCryptPasswordEncoder();

}

}

JWT 工具类

创建一个工具类用于生成和验证 JWT。

public class JWTUtil {

private static final String SECRET_KEY = "your_secret_key";

public static String generateToken(Authentication auth) {

return Jwts.builder()

.setSubject(auth.getName())

.setExpiration(new Date(System.currentTimeMillis() + 864_000_000)) // 10 days

.signWith(SignatureAlgorithm.HS512, SECRET_KEY.getBytes())

.compact();

}

public static Claims getClaims(String token) {

return Jwts.parser()

.setSigningKey(SECRET_KEY.getBytes())

.parseClaimsJws(token)

.getBody();

}

public static boolean validateToken(String token) {

try {

Jwts.parser().setSigningKey(SECRET_KEY.getBytes()).parseClaimsJws(token);

return true;

} catch (JwtException | IllegalArgumentException e) {

return false;

}

}

}

认证过滤器

创建一个过滤器用于处理登录认证。

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

private AuthenticationManager authenticationManager;

public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {

this.authenticationManager = authenticationManager;

}

@Override

public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {

try {

User creds = new ObjectMapper().readValue(req.getInputStream(), User.class);

return authenticationManager.authenticate(

new UsernamePasswordAuthenticationToken(

creds.getUsername(),

creds.getPassword(),

new ArrayList<>())

);

} catch (IOException e) {

throw new RuntimeException(e);

}

}

@Override

protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException {

String token = JWTUtil.generateToken(auth);

res.addHeader("Authorization", "Bearer " + token);

}

}

授权过滤器

创建一个过滤器用于处理请求授权。

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

public JWTAuthorizationFilter(AuthenticationManager authManager) {

super(authManager);

}

@Override

protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {

String header = req.getHeader("Authorization");

if (header == null || !header.startsWith("Bearer ")) {

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("Authorization");

if (token != null) {

String user = JWTUtil.getClaims(token.replace("Bearer ", "")).getSubject();

if (user != null) {

return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());

}

return null;

}

return null;

}

}

总结

JWT 提供了一种简洁而强大的方式来进行身份验证和授权,特别适用于分布式系统和微服务架构。Spring Security 通过其强大的扩展机制,使得与 JWT 的集成变得非常简单和高效。通过了解和应用这些技术,开发者可以构建出安全、可靠的现代 Web 应用。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。