详解Spring Cloud服务认证(JWT)
简介
随着微服务架构的广泛应用,越来越多的服务被拆分成多个小的服务来实现业务逻辑。在这些服务之间进行调用时,我们需要确保服务之间的安全性和认证性。JWT(JSON Web Token)是目前流行的一种跨服务认证机制,它基于无状态性的架构,不需要在服务端记录用户状态,能够承载一些声明信息,以相对较为安全的方式在服务之间进行传递。Spring Cloud提供了丰富的功能来支持基于JWT的服务认证机制。
本文将详细讲解Spring Cloud中如何使用JWT来实现服务认证的过程,包括JWT的生成、验证以及在Spring Cloud中的应用。
JWT的生成
首先,我们需要了解JWT的生成机制。一个JWT令牌由三个部分组成:Header、Payload和Signature。Header部分包含了令牌类型和算法类型;Payload部分包含了一些实体的声明(如:用户信息、时间戳等),Payload是JWT的主要内容;Signature部分是对Header和Payload的签名,用于验证Payload的完整性。
在Spring Cloud中,我们可以使用Spring Security来生成JWT令牌。Spring Security中包含了JwtHelper这个类,用于生成、解析、验证JWT令牌。下面是一个生成JWT的示例代码:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
import java.util.Date;
public class JwtUtil {
public final static long EXPIRATION_TIME = 60 * 60 * 1000; // 1 hour
public static String generateToken(User user) {
String authorities = "";
Collection<? extends GrantedAuthority> authorityCollection = user.getAuthorities();
if (authorityCollection != null && !authorityCollection.isEmpty()) {
for (GrantedAuthority authority : authorityCollection) {
authorities += authority.getAuthority() + ",";
}
}
return Jwts.builder()
.setSubject(user.getUsername())
.claim("authorities", authorities)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, "secret")
.compact();
}
}
上述代码中,我们首先定义了一个Token的过期时间,这里设置为1小时。然后,获取用户的权限信息,并将这些权限加入到JWT的Payload中。最后,使用Jwts对象创建一个JWT令牌,并使用HS512算法对Header和Payload进行签名,同时传入一个加密key。
JWT的验证
对于接受到的JWT令牌,我们需要进行验证,以确保Payload中的信息是有效的。Spring Security提供了很多可以设置的配置项,来实现JWT令牌的验证。下面是一个基于Spring Security的JWT验证示例代码:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class JwtAuthenticationFilter {
private final String HEADER = "Authorization";
private final String PREFIX = "Bearer ";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
try {
Authentication authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
private Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER);
if (token != null && token.startsWith(PREFIX)) {
try {
Claims claims = Jwts.parser()
.setSigningKey("secret")
.parseClaimsJws(token.replace(PREFIX, ""))
.getBody();
String username = claims.getSubject();
if (username != null) {
List<GrantedAuthority> authorities = Arrays.stream(claims.get("authorities").toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
return new UsernamePasswordAuthenticationToken(username, null, authorities);
}
} catch (Exception e) {
return null;
}
}
return null;
}
}
上述代码中,我们首先获取请求头中的Authorization,然后验证Authorization的格式是否为"Bearer token"。接着,我们使用Jwts对象解析JWT令牌,并获取用户的信息。最后,使用这些用户信息创建一个UsernamePasswordAuthenticationToken对象,并返回。
Spring Cloud中的应用
经过上述的介绍,我们已经了解了如何生成和验证JWT令牌。在Spring Cloud中,我们需要配置各个服务之间相互通信的JWT认证信息。下面是一个基于Spring Cloud的JWT认证配置示例:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/service1/**").hasRole("ROLE_ADMIN")
.antMatchers("/service2/**").hasRole("ROLE_USER")
.antMatchers("/service3/**").permitAll()
.and()
.addFilter(new JwtAuthenticationFilter())
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}admin")
.roles("ADMIN")
.and()
.withUser("user")
.password("{noop}user")
.roles("USER");
}
}
上述代码中,我们首先使用@EnableWebSecurity注解开启Spring Security的Web安全功能。然后,我们配置了HttpSecurity,限制了各个服务的角色访问权限。接着,我们为HttpSecurity添加了JwtAuthenticationFilter过滤器,用于接受和验证JWT令牌。最后,我们配置了两个用户和角色。
结语
通过本文的介绍,现在你已经可以使用JWT来实现Spring Cloud中的服务认证机制了。在生产环境中,请一定保护好JWT令牌和加密key,以确保服务的安全性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解SpringCloud服务认证(JWT) - Python技术站