【发布时间】:2020-06-06 17:00:11
【问题描述】:
我有两个微服务,即网关服务和用户服务。网关服务将登录的调用重定向到用户服务。用户服务将生成带有角色和权限等信息的 jwt 令牌,并将其附加到响应头中。
现在客户端可以调用用户服务来创建用户。在请求中传递 jwt 令牌,网关服务验证令牌并将调用转发给用户服务。由于我需要检查登录用户是否具有写入权限(基于@PreAuthorize),我需要在用户服务中再次读取 JWT 令牌并提取角色和权限。
网关服务WebSecurity类配置方法
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.headers().frameOptions().disable();
http.authorizeRequests()
.antMatchers(HttpMethod.POST, "/user/signup").permitAll()
.antMatchers(HttpMethod.POST, "/user/signin").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new AuthenticationFilter(authenticationManager(), environment));
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
AuthenticationFilter.Class
public class AuthenticationFilter extends BasicAuthenticationFilter{
private final Environment environment;
public AuthenticationFilter(AuthenticationManager authenticationManager, Environment environment) {
super(authenticationManager);
this.environment = environment;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String authHeader = request.getHeader(environment.getProperty("auth.token.header.name"));
if (authHeader == null || !authHeader.startsWith("Bearer")) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String authHeader = request.getHeader(environment.getProperty("auth.token.header.name"));
//validate jwt token code
}
在 application.properties 中启用此项,以便标头中的 jwt 令牌信息从网关传递给用户服务。
zuul.routes.user-service.sensitive-headers=Cookie,Set-Cookie
用户服务WebSecurity类配置方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/**").hasIpAddress(environment.getProperty("api.gateway.ip"))
.and()
.addFilter(getAuthenticationFilter());
http.headers().frameOptions().disable();
}
private AuthenticationFilter getAuthenticationFilter() throws Exception{
AuthenticationFilter filter = new AuthenticationFilter(usersService, environment, authenticationManager());
filter.setFilterProcessesUrl("/signin");
return filter;
}
UserService AuthenticationFilter 类
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationService userService;
private final Environment environment;
@Autowired
public AuthenticationFilter(AuthenticationService userService, Environment environment, AuthenticationManager authManager) {
this.userService = userService;
this.environment = environment;
super.setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try {
LoginRequestModel creds = new ObjectMapper().readValue(request.getInputStream(), LoginRequestModel.class);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(creds.getEmail(), creds.getPasssword(), new ArrayList<>())
);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
//generate jwt token code
}
}
现在如何读取网关服务发送的 jwt 令牌的值并设置为安全上下文身份验证。我需要再写一个过滤器吗?该过滤器将来自何处。不应为注册或登录执行该过滤器。任何帮助将不胜感激。
【问题讨论】:
标签: java spring-boot filter jwt jwt-auth