首页 文章

使用Springboot进行JWT身份验证

提问于
浏览
0

我正在使用SpringBoot开发一个带有微服务架构的Rest后端 . 为了保护 endpoints ,我使用了JWT令牌机制 . 我正在使用Zuul API网关 .

如果请求具有所需权限(来自JWT的ROLE)将转发到正确的微服务 . Zuul api网关的“WebSecurityConfigurerAdapter”如下 .

@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服务器安全性的微服务?

1 回答

  • 1

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

    我的microservces应用程序流程,我已实现,如下图所示:
    enter image description here

    流程应该是这样的:https://tools.ietf.org/html/rfc6749#page-7

    关于流程的简短介绍:

    • 登录时,您应该传递用户凭据

    • 如果请求具有上下文路径"/security"(例如),您应该将请求重定向到AuthServer(您决定安全实现)

    • 如果用户传递可用凭据,则AuthServer必须返回access_token .

    • 拥有访问令牌,用户可以向AccountServices(资源服务)发出请求;

    在AccountServices中,您必须实现一个配置类来解码access_token并检查用户是否有权访问所请求的资源

    你也可以在这里找到关于在Spring中实现的OAuth2框架的好文档:http://projects.spring.io/spring-security-oauth/docs/oauth2.html

    一些代码:

    • On 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());
    }
    }
    

    About public and private keys: 私钥只能由AuthServer知道,并且必须在包括AuthService在内的任何服务中传递公钥 . 您可以在此处生成公钥和私钥:http://travistidwell.com/jsencrypt/demo/并在application.yml文件中添加这些密钥,并使用 @Value 传递到配置类 .

    • On Resource server
    @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_token并检查用户是否有ROLE来执行某些操作......在这里,您必须以相同的方式传递 public key application.yml文件 .

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

相关问题