JSON Web Token (JWT) 是一个自我认证的记号,能够包含用户标识、角色和用户权限等信息,能够被任何人方便解析和使用安全的key实现验证,具体可参考这里。
结合JWT的微服务能够避免会话Session开销,同时方便跨多机分布式系统,这样不需要每个服务都要调用专门的授权服务以确认用户操作本服务的权限。另外一个优点是JWT足够小,能够被序列化附加在请求头部内。
第一个带有用户名和密码的请求提交POST到一个未受保护的登录授权REST端点,一旦用户和密码通过授权,响应中将包含一个JWT,以后的请求都会把这个JWT记号带在HTTP头部中,形式像: Authorization: xxxxx.yyyyy.zzzzz
任何服务到服务的请求会一路传递这个请求头部,这样授权信息都可以应用在一路传递的服务中,这些服务都可以检查这个JWT,以决定是否接受访问。
下面以Spring cloud代码为案例,使用JWT的Java实现: Java JWT
public class JsonWebTokenUtility {
private SignatureAlgorithm signatureAlgorithm;
private Key secretKey;
public JsonWebTokenUtility() {
// 这里不是真正安全的实践
// 为了简单,我们存储一个静态key在这里,
// 在真正微服务环境,这个key将会被保留在配置服务器
signatureAlgorithm = SignatureAlgorithm.HS512;
String encodedKey =
"L7A/6zARSkK1j7Vd5SDD9pSSqZlqF7mAhiOgRbgv9Smce6tf4cJnvKOjtKPxNNnWQj+2lQEScm3XIUjhW+YVZg==";
secretKey = deserializeKey(encodedKey);
}
public String createJsonWebToken(AuthTokenDetailsDTO authTokenDetailsDTO)
{
String token =
Jwts.builder().setSubject(authTokenDetailsDTO.userId).claim("email",
authTokenDetailsDTO.email)
.claim("roles", authTokenDetailsDTO.roleNames)
.setExpiration(authTokenDetailsDTO.expirationDate)
.signWith(getSignatureAlgorithm(),
getSecretKey()).compact();
return token;
}
private Key deserializeKey(String encodedKey) {
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
Key key =
new SecretKeySpec(decodedKey, getSignatureAlgorithm().getJcaName());
return key;
}
private Key getSecretKey() {
return secretKey;
}
public SignatureAlgorithm getSignatureAlgorithm() {
return signatureAlgorithm;
}
public AuthTokenDetailsDTO parseAndValidate(String token) {
AuthTokenDetailsDTO authTokenDetailsDTO = null;
try {
Claims claims =
Jwts.parser().setSigningKey(getSecretKey()).parseClaimsJws(token).getBody();
String userId = claims.getSubject();
String email = (String) claims.get("email");
List roleNames = (List) claims.get("roles");
Date expirationDate = claims.getExpiration();
authTokenDetailsDTO = new AuthTokenDetailsDTO();
authTokenDetailsDTO.userId = userId;
authTokenDetailsDTO.email = email;
authTokenDetailsDTO.roleNames = roleNames;
authTokenDetailsDTO.expirationDate = expirationDate;
} catch (JwtException ex) {
System.out.println(ex);
}
return authTokenDetailsDTO;
}
private String serializeKey(Key key) {
String encodedKey =
Base64.getEncoder().encodeToString(key.getEncoded());
return encodedKey;
}
}
现在有了这个工具类,我就可以在每个微服务中设置Spring Security。
现在我们需要一个定制授权过滤器,将能读取请求头部信息,在Spring中已经有一个这样的授权Filter称为:RequestHeaderAuthenticationFilter,我们只要扩展继承即可:
public class JsonWebTokenAuthenticationFilter extends RequestHeaderAuthenticationFilter {
public JsonWebTokenAuthenticationFilter() {
// Don't throw exceptions if the header is missing
this.setExceptionIfHeaderMissing(false);
// This is the request header it will look for
this.setPrincipalRequestHeader("Authorization");
}
@Override
@Autowired
public void setAuthenticationManager(
AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
}
在这里,头部信息将被转换为Spring Authentication 对象,名称为PreAuthenticatedAuthenticationToken
我们需要一个授权提供者读取这个记号,然偶验证它,然后转换为我们自己的定制授权对象:
public class JsonWebTokenAuthenticationProvider implements AuthenticationProvider {
private JsonWebTokenUtility tokenService = new JsonWebTokenUtility();
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Authentication authenticatedUser = null;
// Only process the PreAuthenticatedAuthenticationToken
if (authentication.getClass().
isAssignableFrom(PreAuthenticatedAuthenticationToken.class)
&& authentication.getPrincipal() != null) {
String tokenHeader = (String) authentication.getPrincipal();
UserDetails userDetails = parseToken(tokenHeader);
if (userDetails != null) {
authenticatedUser =
new JsonWebTokenAuthentication(userDetails, tokenHeader);
}
} else {
// It is already a JsonWebTokenAuthentication
authenticatedUser = authentication;
}
return authenticatedUser;
}
private UserDetails parseToken(String tokenHeader) {
UserDetails principal = null;
AuthTokenDetailsDTO authTokenDetails =
tokenService.parseAndValidate(tokenHeader);
if (authTokenDetails != null) {
List<GrantedAuthority> authorities =
authTokenDetails.roleNames.stream()
.map(roleName -> new
SimpleGrantedAuthority(roleName)).collect(Collectors.toList());
principal = new User(authTokenDetails.email, "",
authorities);
}
return principal;
}
@Override
public boolean supports(Class<?> authentication) {
return
authentication.isAssignableFrom(
PreAuthenticatedAuthenticationToken.class)||
authentication.isAssignableFrom(
JsonWebTokenAuthentication.class);
}
}
使用这些组件,我们现在就可以有使用JWT的标准Spring Securtiy安全机制,当我们进行服务对服务调用时,我们需要一路传输JWT。
这里虚构一个客户端,将JWT作为参数传递:
@FeignClient("user-management-service")
public interface UserManagementServiceAPI {
@RequestMapping(value = "/authenticate", method = RequestMethod.POST) AuthTokenDTO authenticateUser(@RequestBody AuthenticationDTO authenticationDTO);
@RequestMapping(method = RequestMethod.POST, value = "/roles") RoleDTO createRole(@RequestHeader("Authorization") String authorizationToken, @RequestBody RoleDTO roleDTO);
@RequestMapping(method = RequestMethod.POST, value = "/users") UserDTO createUser(@RequestHeader("Authorization") String authorizationToken, @RequestBody UserDTO userDTO);
@RequestMapping(method = RequestMethod.DELETE, value = "/roles/{id}") void deleteRole(@RequestHeader("Authorization") String authorizationToken, @PathVariable("id") int id);
@RequestMapping(method = RequestMethod.DELETE, value = "/users/{id}") void deleteUser(@RequestHeader("Authorization") String authorizationToken, @PathVariable("id") int id);
@RequestMapping(method = RequestMethod.GET, value = "/roles") Collection<RoleDTO> findAllRoles(@RequestHeader("Authorization") String authorizationToken);
@RequestMapping(method = RequestMethod.GET, value = "/users") Collection<UserDTO> findAllUsers(@RequestHeader("Authorization") String authorizationToken);
@RequestMapping(method = RequestMethod.GET, value = "/roles/{id}", produces = "application/json", consumes = "application/json") RoleDTO findRoleById(@RequestHeader("Authorization") String authorizationToken, @PathVariable("id") int id);
@RequestMapping(method = RequestMethod.GET, value = "/users/{id}", produces = "application/json", consumes = "application/json") UserDTO findUserById(@RequestHeader("Authorization") String authorizationToken, @PathVariable("id") int id);
@RequestMapping(method = RequestMethod.GET, value = "/users/{id}/roles") Collection<RoleDTO> findUserRoles(@RequestHeader("Authorization") String authorizationToken, @PathVariable("id") int id);
@RequestMapping(method = RequestMethod.PUT, value = "/roles/{id}") void updateRole(@RequestHeader("Authorization") String authorizationToken, @PathVariable("id") int id, @RequestBody RoleDTO roleDTO);
@RequestMapping(method = RequestMethod.PUT, value = "/users/{id}") void updateUser(@RequestHeader("Authorization") String authorizationToken, @PathVariable("id") int id, @RequestBody UserDTO userDTO);
}
为了一路传递JWT,在我们自己的控制器中模仿Spring Security实现如下:
private String getAuthorizationToken() {
String token = null;
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
if (authentication != null &&
authentication.getClass().
isAssignableFrom(JsonWebTokenAuthentication.class)) {
JsonWebTokenAuthentication jwtAuthentication =
(JsonWebTokenAuthentication) authentication;
token = jwtAuthentication.getJsonWebToken();
}
return token;
}
正如你看到,在一个分布式微服务环境中,JWT提供了灵活的授权。
项目源码:Github
http://www.jdon.com/dl/best/json-web-tokens-spring-cloud-microservices.html
相关推荐
它支持多种认证方式,如基于用户名和密码的传统认证、OAuth2认证,以及JWT(JSON Web Tokens)等现代认证机制。同时,课程会教授如何设置权限控制,防止未授权访问服务接口。 在API Gateway层面,课程将教授如何...
8. **安全性**:系统应具备用户身份验证和授权机制,可能使用JWT(JSON Web Tokens)进行安全的身份验证,以及OAuth 2.0进行权限管理,保护用户数据和竞赛过程的安全。 9. **监控与日志**:为了确保系统的稳定运行...
视频教程是学习这些技术的有效途径,涵盖了JAVAEE架构的基础知识、SpringBoot和SpringCloud的实战应用,以及微服务架构的设计和实现。通过观看视频,学习者可以更直观地了解这些技术的工作原理,同时也能获取到实际...
- JWT(JSON Web Tokens)或OAuth2进行身份验证和授权。 - Swagger或类似的工具来生成和文档化API接口。 - Spring Security进行权限控制和访问控制。 - 测试框架如JUnit和Mockito,用于单元测试和集成测试。 - CI/CD...
总的来说,"SpringBoot+SpringSecurity+JWT权限管理练习项目"是一个全面而实用的学习资源,它将帮助初学者系统地掌握现代Web应用中的安全设计和实现。通过实际操作,学习者能够更好地理解这些技术的内在联系,从而在...
3. JWT令牌认证:使用JSON Web Tokens进行用户身份验证,SpringCloud服务端验证令牌,Vue.js前端存储和发送令牌。 4. 路由管理:Vue.js的router模块进行页面路由管理,SpringCloud API Gateway处理不同服务的路由...
在Spring Cloud中,使用`ResourceServerConfigurerAdapter`进行配置,通常需要配置访问令牌的解析方式,如JWT(JSON Web Tokens)或者OAuth2的Resource Server端点。 单点登录(SSO)允许用户在一个系统登录后,...
- 在微服务架构中,权限管理是关键部分,通常通过OAuth2.0、JWT(JSON Web Tokens)等方式实现用户认证和授权。 - Spring Security可以与Spring Boot结合,提供一套完整的安全解决方案,包括角色权限分配、登录...
安全验证方面,通常会使用OAuth2或者JWT(JSON Web Tokens)进行用户认证和授权,保护API接口的安全。此外,项目可能还采用了Spring Security进行权限控制,确保只有合法用户才能访问特定资源。 Vue.js全家桶中的...
1. **身份验证**:用户需要通过用户名和密码、OAuth2令牌、JWT(JSON Web Tokens)等方式进行身份验证。Spring Security可以配置多种认证方式,例如使用Spring Security的Remember Me服务实现自动登录。 2. **角色...
9. **安全性**:OAuth2、JWT(JSON Web Tokens)等技术用于实现服务之间的身份验证和授权,Spring Security 或 Apache Shiro 可以增强应用的安全性。 通过"finance"这个文件名,我们可以推测这个压缩包可能包含了与...
在SpringCloud中,我们通常使用OAuth2或者JWT(JSON Web Tokens)来实现SSO。 1. **OAuth2**: OAuth2是一个授权框架,允许第三方应用在用户的许可下访问其私有资源。在SSO场景中,我们可以将OAuth2用作认证服务器...
《微服务商城系统》是基于Spring Security Oauth2与JWT技术实现用户...以上就是基于Spring Security Oauth2和JWT的用户认证微服务的核心知识,这个系统的设计和实现充分体现了现代电商系统的安全性、可扩展性和灵活性。
这包括定义认证和授权的规则,例如基于JWT(JSON Web Tokens)的认证,或者基于OAuth2的授权流程。 3. **定制Filter**:在Spring Cloud Gateway中,我们可以自定义WebFlux Filter,利用Spring Security提供的API...
6. 安全性:使用HTTPS协议保障数据传输安全,配合JWT(JSON Web Tokens)进行权限验证。 7. 监控与日志:通过Spring Boot Actuator监控服务健康状况,使用Logback或Log4j记录应用日志。 此外,开发过程中还需要考虑...
在构建现代Web应用程序时,Spring Boot、Spring Security和JWT(JSON Web Tokens)是常见的技术组合。这个项目结合了这三个组件,以提供一个适用于微服务架构的身份验证和授权解决方案。下面我们将详细探讨这些技术...
10. **安全策略**:可能使用OAuth2进行权限验证,JWT(JSON Web Tokens)处理用户认证,以及HTTPS确保数据传输的安全。 以上是对“Java基于微服务架构实现的智能招聘系统”项目的关键技术点的解析。通过这样的设计...
7. 身份验证与令牌管理:实现OAuth2或JWT(JSON Web Tokens)的身份验证机制。 通过阅读这本书和实践源码,开发者不仅能了解Spring Boot的基本用法,还能掌握其高级特性和最佳实践,从而提升开发效率,打造高质量的...
Spring Security、OAuth2和JWT(JSON Web Tokens)是实现安全控制的关键技术。本项目“SpringSecurity+OAuth2+JWT分布式权限控制”旨在提供一个完整的解决方案,帮助开发者构建安全的、基于微服务的分布式应用程序。...
JWT(JSON Web Tokens)在此过程中扮演了重要角色,它是一种轻量级的身份验证和授权机制。JWT包含三个部分:头部、载荷和签名,所有数据都在令牌中加密,可以在客户端和服务端之间安全传输,无需存储会话信息在...