使用Springboot的JWT身份验证

使用Springboot的JWT身份验证,spring,spring-boot,spring-security,netflix-zuul,Spring,Spring Boot,Spring Security,Netflix Zuul,我正在使用SpringBoot开发一个具有微服务体系结构的Rest后端。为了保护端点,我使用了JWT令牌机制。我正在使用zuulapi网关 如果请求具有所需的权限(来自JWT的角色),它将转发到正确的微服务。Zuul api网关的“WebSecurity配置适配器”如下所示 @Autowired private JwtAuthenticationConfig config; @Bean public JwtAuthenticationConfig jwtConfig() { retur

我正在使用SpringBoot开发一个具有微服务体系结构的Rest后端。为了保护端点,我使用了JWT令牌机制。我正在使用zuulapi网关

如果请求具有所需的权限(来自JWT的角色),它将转发到正确的微服务。Zuul api网关的“WebSecurity配置适配器”如下所示

@Autowired
private JwtAuthenticationConfig config;

@Bean
public JwtAuthenticationConfig jwtConfig() {
    return new JwtAuthenticationConfig();
}

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            .csrf().disable()
            .logout().disable()
            .formLogin().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .anonymous()
            .and()
                .exceptionHandling().authenticationEntryPoint(
                        (req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
            .and()
                .addFilterAfter(new JwtTokenAuthenticationFilter(config),
                        UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers(config.getUrl()).permitAll()
                .antMatchers("/api/user/**").permitAll()
                .antMatchers("/api/package/**").hasRole("USER")
                .antMatchers("/api/dashboard/**").hasRole("USER")
                .antMatchers("/api/records/**").hasRole("USER");
}
这样,我必须在这个类中编写每个请求授权部分。所以我希望使用方法级安全性,即“EnableGlobalMethodSecurity”

问题是我应该如何将这个安全机制与其他微服务连接起来。因为当我将spring安全依赖性添加到其他微服务时,它们表现为不同的spring安全模块。我应该如何告诉其他使用zuul服务器安全性的微服务

首先(如果我正确理解的话)安全实现是在代理上的吗?因为代理必须只有两件事要做:过滤和路由

我已经实现的microservices应用程序流程如下图所示:

流程应该是这样的:

流程简介:

  • 登录时,您应该传递用户凭据
  • 如果请求具有上下文路径“/security”(例如),则应将请求重定向到AuthServer(由您决定安全实现)
  • 如果用户传递可用凭据,AuthServer必须返回访问令牌
  • 拥有用户能够向AccountServices(资源服务)发出请求的访问令牌
  • 在AccountServices中,您必须实现一个配置类来解码访问令牌,并检查用户是否有权访问请求的资源

    您也可以在这里找到一个关于在Spring中实现的OAuth2框架的好文档:

    一些代码:

  • AuthService上的

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
    public final static String RESOURCE_ID = "server-resource";
    
    @Value("${jwt.publicKey}")
    private String publicKey;
    
    @Value("${jwt.privateKey}")
    private String privateKey;
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }
    
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setVerifierKey(publicKey);
        converter.setSigningKey(privateKey);
        return converter;
    }
    
    @Bean
    public TokenEnhancer customTokenEnhancer() {
        return new CustomTokenEnhancer();
    }
    
    @Override
    public void configure(ClientDetailsServiceConfigurer client) throws Exception {
        client.inMemory()
            .withClient("client")
            .secret("clientsecret")
            .scopes("read", "write")
            .resourceIds("user")
            .authorizedGrantTypes("password", "refresh_token", "authorization_code")
            .authorities("ROLE_TRUSTED_CLIENT")
            .accessTokenValiditySeconds(tokenExpire) // one day available
            .refreshTokenValiditySeconds(refreshExpire);
    }
    
    @Override
    public void configure(AuthorizationServerSecurityConfigurer server) throws Exception {
        server
            .tokenKeyAccess("hasAuthority('ROLE_TRUSTED_CLIENT')")
            .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')"); 
    }
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
            .tokenStore(tokenStore())
            .authenticationManager(authenticationManager)
            .accessTokenConverter(accessTokenConverter());
    }
    }
    
  • 关于公钥和私钥:私钥必须仅由AuthServer知道,并且必须在任何服务(包括AuthService)中传递公钥。您可以在此处生成公钥和私钥:并将这些密钥添加到application.yml文件中,然后使用
    @Value
    传递到配置类中

  • 在资源服务器上

    @Configuration
    @EnableResourceServer
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class OAuth2ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    
    @Value("${jwt.publicKey}")
    private String publicKey;
    
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    
    @Bean
    protected JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setVerifierKey(publicKey);
        return converter;
    }
    
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources
            .tokenStore(tokenStore())
            .resourceId("user");
    }
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests().antMatchers("/**").permitAll();
    }
    
    }
    
  • 您必须做的唯一一件事是为资源服务(AccountService)创建一个配置类来解码access_令牌,并检查用户是否具有执行某些操作的角色。。。在这里,您必须以相同的方式传递application.yml文件,仅传递公钥

    关于
    @EnableGlobalMethodSecurity(prespenabled=true)
    注释您可以在控制器方法上添加
    @preauthorize
    注释