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

基于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

  • 主要内容:1. 前提条件,2. 配置工作,3. 允许多人进入,4. 可能的问题,5. 替代密码存储,6. 使用多个供应者,7. 超越授权身份验证是验证访问者是否是他们所声称的人的任何过程。授权是允许访问者进入他们想去的地方或获得他们想要的信息的过程。 如果您的网站上的信息仅对一小部分人使用,下面这些技巧将帮助您确保看到这些网页的人员是您想要查看的人。 本文还将介绍保护大多数人将要使用的网站部分的“标准”方法。 1. 前提条件 本文中讨论的指令需要在主服务器配置文件(通常在部分中)或每目录配置文件