我将Zuul用作api网关,以通过在标头中传递jwt令牌来认证用户详细信息, 以下是我在zuul api网关中的Web安全配置文件
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityCongurer extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.csrf().disable()
// make sure we use stateless session; session won't be used to store user's state.
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// handle an authorized attempts
.exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and()
// Add a filter to validate the tokens with every request
.addFilterAfter(new JwtAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class)
// authorization requests config
.authorizeRequests()
// allow all who are accessing "auth" service
.antMatchers(HttpMethod.POST, "/authapi/auth").permitAll()
// must be an admin if trying to access admin area (authentication is also required here)
.antMatchers("/authapi/user/**").hasRole("ADMIN")
// Any other request must be authenticated
.anyRequest().authenticated();
}
}
下面是我的身份验证过滤器类
public class JwtAuthorizationFilter extends OncePerRequestFilter{
@Autowired
public JwtProperties jwtProperties;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
// Read the Authorization header, where the JWT token should be
String header = request.getHeader(JwtProperties.HEADER_STRING);
// If header does not contain BEARER or is null delegate to Spring impl and exit
if (header == null || !header.startsWith(JwtProperties.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
String token = request.getHeader(JwtProperties.HEADER_STRING)
.replace(JwtProperties.TOKEN_PREFIX,"");
try { // exceptions might be thrown in creating the claims if for example the token is expired
// 4. Validate the token
Claims body = Jwts.parser()
.setSigningKey(JwtProperties.SECRET.getBytes())
.parseClaimsJws(token)
.getBody();
String value = String.valueOf(body.get("role"));
String valuerole = value.substring(12,22);
GrantedAuthority authorityyy = new SimpleGrantedAuthority(valuerole);
String username = body.getSubject();
if(username != null) {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(authorityyy);
// 5. Create auth object
// UsernamePasswordAuthenticationToken: A built-in object, used by spring to represent the current authenticated / being authenticated user.
// It needs a list of authorities, which has type of GrantedAuthority interface, where SimpleGrantedAuthority is an implementation of that interface
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
username, body.get("password"),authorities);
// 6. Authenticate the user
// Now, user is authenticated
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (Exception e) {
// In case of failure. Make sure it's clear; so guarantee user won't be authenticated
SecurityContextHolder.clearContext();
}
// Continue filter execution
chain.doFilter(request, response); // last pointer
}
}
当指针指向chain.doFilter(request,response);时,我一直停留在这里。行,它会显示未经授权的401错误。
这是我的application.properties,
server.port=8762
spring.application.name=zuul-server
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
zuul.ignored-services=*
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=true
zuul.routes.auth-service.service-id=AUTH-SERVICE
zuul.routes.auth-service.path=/authapi/**
zuul.routes.auth-service.sensitive-headers=Cookie,Set-Cookie
ribbon.ReadTimeout=60000
上面是我的zuul api网关文件。
现在添加用于生成令牌的用户身份验证服务文件。
下面是用于用户身份验证的Web安全配置文件,
@Configuration
@EnableWebSecurity
@ComponentScan("com.userManagementService.ServiceUserCredentials.*")
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfigurer extends WebSecurityConfigurerAdapter{
@Autowired
public UserOperationService userOperationService;
@Autowired
public MyUserDetailsService myUserDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.csrf().disable()
// make sure we use stateless session; session won't be used to store user's state.
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// handle an authorized attempts
.exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and()
// Add a filter to validate user credentials and add token in the response header
// What's the authenticationManager()?
// An object provided by WebSecurityConfigurerAdapter, used to authenticate the user passing user's credentials
// The filter needs this auth manager to authenticate the user.
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.authorizeRequests()
// allow all POST requests
.antMatchers(HttpMethod.POST, "/auth").permitAll()
// any other requests must be authenticated
.anyRequest().authenticated();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
DaoAuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
daoAuthenticationProvider.setUserDetailsService(myUserDetailsService);
return daoAuthenticationProvider;
}
}