面试题答案
一键面试技术选型
- 生成与验证Token:通常选用JSON Web Token(JWT)。JWT是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON对象的形式安全地传输信息。在Java中,常用的库有
jjwt
。 - 存储用户信息:可以使用关系型数据库(如MySQL)或NoSQL数据库(如Redis)。如果选择Redis,因其高性能的读写能力,非常适合存储与用户认证相关的短期数据,如用户登录状态等。
关键代码片段
- 生成Token:
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import java.util.HashMap; import java.util.Map; public class TokenUtil { private static final String SECRET_KEY = "your_secret_key"; public static String generateToken(String username) { Map<String, Object> claims = new HashMap<>(); claims.put("sub", username); claims.put("iat", new Date()); claims.put("exp", new Date(System.currentTimeMillis() + 10 * 60 * 1000));// 10分钟过期 return Jwts.builder() .setClaims(claims) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } }
- 验证Token:
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureException; public class TokenUtil { private static final String SECRET_KEY = "your_secret_key"; public static boolean validateToken(String token) { try { Claims claims = Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); Date expiration = claims.getExpiration(); return!expiration.before(new Date()); } catch (SignatureException | IllegalArgumentException e) { return false; } } }
Token在各微服务间传递的流程
- 用户登录:
- 用户在客户端输入用户名和密码,发送登录请求到认证服务微服务。
- 认证服务微服务验证用户输入的用户名和密码是否正确。如果正确,调用
TokenUtil.generateToken
方法生成Token,并将Token返回给客户端。
- 客户端请求其他微服务:
- 客户端在收到Token后,在后续每次请求其他微服务时,将Token放在HTTP请求的
Authorization
头中,格式为Bearer {token}
。例如:Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VybmFtZSIsImlhdCI6MTYxNjM0MjQ1NSwiZXhwIjoxNjE2MzQzMDU1fQ.Gz81Z20f4t05X8Gj758z5894754786547865
。
- 客户端在收到Token后,在后续每次请求其他微服务时,将Token放在HTTP请求的
- 微服务接收请求并验证Token:
- 每个需要认证的微服务在接收到请求时,从
Authorization
头中提取Token。 - 调用
TokenUtil.validateToken
方法验证Token的有效性。如果Token有效,则处理请求;如果无效,则返回未授权错误(如HTTP 401状态码)。
- 每个需要认证的微服务在接收到请求时,从
- 微服务间调用:
- 如果一个微服务需要调用另一个微服务,并且被调用的微服务也需要认证,调用方微服务需要将从客户端接收到的Token传递给被调用方微服务。可以在Feign等微服务调用工具中进行配置,使其在调用时自动带上Token。例如,在Feign的配置类中:
这样,在微服务间通过Feign调用时,Token会被自动传递,保证了整个分布式系统中认证状态的一致性。import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @Configuration public class FeignConfig { @Bean public RequestInterceptor requestInterceptor() { return new RequestInterceptor() { @Override public void apply(RequestTemplate template) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes!= null) { String token = attributes.getRequest().getHeader("Authorization"); if (token!= null) { template.header("Authorization", token); } } } }; } }