当前位置: 首页 > 知识库问答 >
问题:

基于JWT的认证、验证和授权方案的Spring Security过滤器示例

羊新翰
2023-03-14

Java Spring(和Spring Security)在这里,有兴趣使用持有者令牌为我的Web服务实现基于JWT的身份验证机制。我对使用Spring Security进行身份验证和授权的正确方式的理解是通过使用提供的(或自定义的)过滤器,如下所示:

  • 指定应用中的哪些 URL 经过身份验证(因此需要经过身份验证的请求才能访问)
    • 这通常是在@EnableWebSecurity注释的Web安全类中完成的,该类扩展了WebSecurityConfigurerAdapter
    • 请求客户端应首先命中此登录endpoint(authn筛选器),以获取可用于进行后续API调用的auth令牌。
    • 此筛选器应接收一种类型的“登录请求”对象,该对象包含主体(如用户名)和凭证(如密码)。
    • 此身份验证筛选器应使用登录请求中包含的主体/凭据来确定它们是否代表系统中的有效用户
      • 如果是,将生成身份验证令牌(JWT等),并以某种方式在响应中发送回请求者。
      • 否则,如果主体/凭据与系统中的有效用户不匹配,则返回错误响应,身份验证失败
      • 如果身份验证令牌有效,请求将继续到授权筛选器(请参见下文)
      • 否则,如果身份验证令牌无效,验证将失败,过滤器将向客户端发送错误响应
      • 如果它们这样做,则允许请求继续到为处理它而编写的任何资源/控制器,并且该资源/控制器将响应提供回请求者
      • 如果没有,则向客户端返回错误响应
      • 理想情况下,此Authz过滤器中的逻辑(代码)将有权访问添加到资源方法中的权限注释,以便我可以添加endpoint并指定对它们的权限,而无需修改Authz过滤器的代码

      因此,首先,如果我上面所说的任何内容是Spring Security(或一般的Web安全)反模式或被误导,请首先提供课程更正并引导我走向正确的方向!

      假设我或多或少正确理解了上面的“授权流”。。。

      是否有任何特定的Spring Security过滤器已经为我处理了所有这些,或者可以扩展并覆盖一些方法以实现这种行为?或者任何非常接近的东西?查看特定于身份验证的Spring Security过滤器列表,我看到:

      • 用户名密码身份验证过滤器 -

      至于令牌验证和授权,我(令我惊讶的是)在Spring Security领域看不到任何符合条件的东西。

      除非有人知道我可以轻松使用或子类的特定于JWT的过滤器,否则我认为我需要实现自己的自定义过滤器,在这种情况下,我想知道如何使用Spring Security来使用它们,而不是使用任何其他身份验证过滤器(例如UsernamePasswordAuthenticationFilter)作为过滤器链的一部分。

共有1个答案

赵英资
2023-03-14

据我所知,您希望:

  1. 通过用户名和密码验证用户,并使用JWT进行响应。
  2. 在后续请求中,使用该JWT对用户进行身份验证

用户名/密码 -

不过,你可以很容易地自己得到它。

首先,创建一个生成 JWT 的 /token 终结点:

@RestController
public class TokenController {

    @Value("${jwt.private.key}")
    RSAPrivateKey key;

    @PostMapping("/token")
    public String token(Authentication authentication) {
        Instant now = Instant.now();
        long expiry = 36000L;
        // @formatter:off
        String scope = authentication.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.joining(" "));
        JWTClaimsSet claims = new JWTClaimsSet.Builder()
                .issuer("self")
                .issueTime(new Date(now.toEpochMilli()))
                .expirationTime(new Date(now.plusSeconds(expiry).toEpochMilli()))
                .subject(authentication.getName())
                .claim("scope", scope)
                .build();
        // @formatter:on
        JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).build();
        SignedJWT jwt = new SignedJWT(header, claims);
        return sign(jwt).serialize();
    }

    SignedJWT sign(SignedJWT jwt) {
        try {
            jwt.sign(new RSASSASigner(this.key));
            return jwt;
        }
        catch (Exception ex) {
            throw new IllegalArgumentException(ex);
        }
    }

}

其次,配置Spring Security以允许HTTP Basic(对于< code>/tokenendpoint)和JWT(对于其余endpoint):

@Configuration
public class RestConfig extends WebSecurityConfigurerAdapter {

    @Value("${jwt.public.key}")
    RSAPublicKey key;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.authorizeRequests((authz) -> authz.anyRequest().authenticated())
            .csrf((csrf) -> csrf.ignoringAntMatchers("/token"))
            .httpBasic(Customizer.withDefaults())
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
            .sessionManagement((session) -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .exceptionHandling((exceptions) -> exceptions
                .authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
                .accessDeniedHandler(new BearerTokenAccessDeniedHandler())
            );
        // @formatter:on
    }

    @Bean
    UserDetailsService users() {
        // @formatter:off
        return new InMemoryUserDetailsManager(
            User.withUsername("user")
                .password("{noop}password")
                .authorities("app")
                .build());
        // @formatter:on
    }

    @Bean
    JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withPublicKey(this.key).build();
    }

}

我认为,如果您有兴趣贡献自己的努力,可以在<code>spring authorization server

 类似资料:
  • 我们在 remember-me-hash上,基于 Form 表单的方式,来实现基于散列的令牌方法的 Remember-Me 认证,我们新建一个 jwt-authentication项目。 build.gradle 修改 build.gradle 文件,让我们的remember-me-hash项目成为一个新的项目。 修改内容也比较简单,修改项目名称及版本即可。 jar { baseName

  • 本文向大家介绍Springboot+SpringSecurity+JWT实现用户登录和权限认证示例,包括了Springboot+SpringSecurity+JWT实现用户登录和权限认证示例的使用技巧和注意事项,需要的朋友参考一下 如今,互联网项目对于安全的要求越来越严格,这就是对后端开发提出了更多的要求,目前比较成熟的几种大家比较熟悉的模式,像RBAC 基于角色权限的验证,shiro框架专门用于

  • 本文向大家介绍ASP.NET Core使用JWT认证授权的方法,包括了ASP.NET Core使用JWT认证授权的方法的使用技巧和注意事项,需要的朋友参考一下  demo地址: https://github.com/william0705/JWTS 名词解析 认证 : 识别用户是否合法 授权: 赋予用户权限 (能访问哪些资源) 鉴权: 鉴定权限是否合法 Jwt优势与劣势 优势 1、 无状态 tok

  • 本文向大家介绍Spring Cloud下基于OAUTH2认证授权的实现示例,包括了Spring Cloud下基于OAUTH2认证授权的实现示例的使用技巧和注意事项,需要的朋友参考一下 在Spring Cloud需要使用OAUTH2来实现多个微服务的统一认证授权,通过向OAUTH服务发送某个类型的grant type进行集中认证和授权,从而获得access_token,而这个token是受其他微服务

  • 我实现了一个自定义的身份验证过滤器,效果很好。在设置会话并将身份验证对象添加到安全上下文后,我使用外部身份提供程序并重定向到最初请求的URL。 安全配置 过滤逻辑 目前,我的自定义过滤器(身份确认后)只需硬编码一个角色: 然后将该身份验证对象(上面返回)添加到我的SecurityContext,然后再重定向到所需的endpoint: SecurityContextHolder.getContext

  • 如何在Spring Security中实现基于JWT的身份验证和授权 我试图在我的Spring启动应用程序中实现基于jwt的身份验证和授权。我遵循了这里写的教程。但是它在我的应用程序中没有做任何事情。它不返回jwt令牌,而是我被验证了,我的请求得到了满足。我是Spring安全新手。这是我的代码。 我希望我的应用程序返回jwt令牌,并且使用该令牌必须授权请求。 这是我的密码。 ilter.java