代码之家  ›  专栏  ›  技术社区  ›  Jean Fernandine

我需要在JWT访问令牌中存储额外的用户数据

  •  0
  • Jean Fernandine  · 技术社区  · 3 年前

    我需要将经过身份验证的用户的firstName和id存储在我的访问令牌中,但在调用该属性时,数据返回为空。 请注意,我首先添加声明。

    public OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() {
            return context -> {
                OAuth2ClientAuthenticationToken principal = context.getPrincipal();
                CustomUserAuthorities user = (CustomUserAuthorities) principal.getDetails();
                List<String> authorities = user.getAuthorities().stream().map(x -> x.getAuthority()).toList();
                if (context.getTokenType().getValue().equals("access_token")) {
                    // @formatter:off
                    context.getClaims()
                            .claim("firstName", user.getFirstName())
                            .claim("authorities", authorities)
                            .claim("username", user.getUsername())
                            .claim("firstName", user.getFirstName())
                    ;
                    // @formatter:on
                }
            };
        }
    

    我正在调用一个具有自定义属性的单独的CustomUserAuthorities类。

    public class CustomUserAuthorities {
    
        private String username;
        private String firstName;
        private Collection<? extends GrantedAuthority> authorities;
    
        public CustomUserAuthorities(String firstName, String username, Collection<? extends GrantedAuthority> authorities) {
            this.username = username;
            this.authorities = authorities;
            this.firstName = firstName;
        }
        public String getUsername() {
            return username;
        }
        public String getFirstName() {
            return firstName;
        }
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return authorities;
        }
    
    }
    

    在CustomPasswordAuthenticationProvider类中,我调用了firstName,并通过调用oAuth2ClientAuthenticationToken.getDetails将其实例化。

    public class CustomPasswordAuthenticationProvider implements AuthenticationProvider {
    
        private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
        private final OAuth2AuthorizationService authorizationService;
        private final UserDetailsService userDetailsService;
        private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
        private final PasswordEncoder passwordEncoder;
    
        private String firstName = "";
        private String username = "";
        private String password = "";
        private Set<String> authorizedScopes = new HashSet<>();
    
        public CustomPasswordAuthenticationProvider(OAuth2AuthorizationService authorizationService,
                OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator, 
                UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
            
            Assert.notNull(authorizationService, "authorizationService cannot be null");
            Assert.notNull(tokenGenerator, "TokenGenerator cannot be null");
            Assert.notNull(userDetailsService, "UserDetailsService cannot be null");
            Assert.notNull(passwordEncoder, "PasswordEncoder cannot be null");
            this.authorizationService = authorizationService;
            this.tokenGenerator = tokenGenerator;
            this.userDetailsService = userDetailsService;
            this.passwordEncoder = passwordEncoder;
        }
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            
            CustomPasswordAuthenticationToken customPasswordAuthenticationToken = (CustomPasswordAuthenticationToken) authentication;
            OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(customPasswordAuthenticationToken);
            RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
            username = customPasswordAuthenticationToken.getUsername();
            password = customPasswordAuthenticationToken.getPassword();
    
            UserDetails user = null;
            try {
                user = userDetailsService.loadUserByUsername(username);
            } catch (UsernameNotFoundException e) {
                throw new OAuth2AuthenticationException("Invalid credentials");
            }
                    
            if (!passwordEncoder.matches(password, user.getPassword()) || !user.getUsername().equals(username)) {
                throw new OAuth2AuthenticationException("Invalid credentials");
            }
    
            authorizedScopes = user.getAuthorities().stream()
                    .map(scope -> scope.getAuthority())
                    .filter(scope -> registeredClient.getScopes().contains(scope))
                    .collect(Collectors.toSet());
            
            //-----------Create a new Security Context Holder Context----------
            OAuth2ClientAuthenticationToken oAuth2ClientAuthenticationToken = (OAuth2ClientAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
            CustomUserAuthorities customPasswordUser = new CustomUserAuthorities(firstName, username, user.getAuthorities());
            oAuth2ClientAuthenticationToken.setDetails(customPasswordUser);
    
            var newcontext = SecurityContextHolder.createEmptyContext();
            newcontext.setAuthentication(oAuth2ClientAuthenticationToken);
            SecurityContextHolder.setContext(newcontext);       
    
    

    我期望返回firstName:经过身份验证的用户的名字。但它返回了“”。空的

    {
      "sub": "myclientid",
      "aud": "myclientid",
      "firstName": "",
      "nbf": 1691786519,
      "iss": "http://localhost:8080",
      "exp": 1692650519,
      "iat": 1691786519,
      "authorities": [
        "ROLE_CLIENT"
      ],
      "username": "[email protected]"
    }
    
    0 回复  |  直到 3 年前