【问题标题】:How get more information for user spring boot如何获取有关用户 spring boot 的更多信息
【发布时间】:2021-04-15 08:17:40
【问题描述】:

大家好,我希望你们一切都好,我已经使用 spring boot 7 个月了,但现在我在墙前 1 周,oauth 2 都作为登录和注册,但在我连接提供的用户信息不足

这是我得到的结果

    {
  "exp": 1610236389,
  "user_name": "fiasco555",
  "authorities": [
    "ROLE_USER"
  ],
  "jti": "1JQTeD5wuRG7vDkIKKg4XUgohZw",
  "client_id": "clientId",
  "scope": [
    "read",
    "write"
  ]

我想了解更多关于我的用户的信息,这里是代码的副本

AuthorizationServerConfiguration.java

import javax.sql.DataSource;
import java.security.KeyPair;

@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(SecurityProperties.class)
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private final DataSource dataSource;
    @Autowired
    private final PasswordEncoder passwordEncoder;
    @Autowired
    private final AuthenticationManager authenticationManager;
    @Autowired
    private final SecurityProperties securityProperties;
    @Autowired
    private final UserDetailsService userDetailsService;
    @Autowired
    private  MyUserDetailsService myUserDetailsService;
    private JwtAccessTokenConverter jwtAccessTokenConverter;
    private TokenStore tokenStore;

    public AuthorizationServerConfiguration(final DataSource dataSource, final PasswordEncoder passwordEncoder,
                                            final AuthenticationManager authenticationManager, final SecurityProperties securityProperties,
                                            final UserDetailsService userDetailsService) {
        this.dataSource = dataSource;
        this.passwordEncoder = passwordEncoder;
        this.authenticationManager = authenticationManager;
        this.securityProperties = securityProperties;
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public TokenStore tokenStore() {
        if (tokenStore == null) {
            tokenStore = new JwtTokenStore(jwtAccessTokenConverter());
        }
        return tokenStore;
    }

    @Bean
    public DefaultTokenServices tokenServices(final TokenStore tokenStore,
                                              final ClientDetailsService clientDetailsService) {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setTokenStore(tokenStore);
        tokenServices.setClientDetailsService(clientDetailsService);
        tokenServices.setAuthenticationManager(this.authenticationManager);
        return tokenServices;

    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        if (jwtAccessTokenConverter != null) {
            return jwtAccessTokenConverter;
        }

        SecurityProperties.JwtProperties jwtProperties = securityProperties.getJwt();
        System.out.println("YESS" + jwtProperties.getKeyPairAlias());
        KeyPair keyPair = keyPair(jwtProperties, keyStoreKeyFactory(jwtProperties));

        jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setKeyPair(keyPair);
        return jwtAccessTokenConverter;
    }

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(this.dataSource);
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(this.authenticationManager)
                .accessTokenConverter(jwtAccessTokenConverter())
                .userDetailsService(this.userDetailsService)
                .tokenStore(tokenStore());
    }

    @Override
    public void configure(final AuthorizationServerSecurityConfigurer oauthServer) {
        oauthServer.passwordEncoder(this.passwordEncoder).tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
    }

    private KeyPair keyPair(SecurityProperties.JwtProperties jwtProperties, KeyStoreKeyFactory keyStoreKeyFactory) {
        return keyStoreKeyFactory.getKeyPair(jwtProperties.getKeyPairAlias(), jwtProperties.getKeyPairPassword().toCharArray());
    }
@Deprecated
    private KeyStoreKeyFactory keyStoreKeyFactory(SecurityProperties.JwtProperties jwtProperties) {
        return new KeyStoreKeyFactory(jwtProperties.getKeyStore(), jwtProperties.getKeyStorePassword().toCharArray());
    }
}

ResourceServerConfiguration.java

import static java.nio.charset.StandardCharsets.UTF_8;
@Configuration
@EnableResourceServer
@EnableConfigurationProperties(SecurityProperties.class)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    private static final String ROOT_PATTERN = "/**";

    private final SecurityProperties securityProperties;

    private TokenStore tokenStore;

    public ResourceServerConfiguration(final SecurityProperties securityProperties) {
        this.securityProperties = securityProperties;
    }

    @Override
    public void configure(final ResourceServerSecurityConfigurer resources) {
        resources.tokenStore(tokenStore());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST,"/register/**").permitAll()
                .antMatchers(HttpMethod.GET, ROOT_PATTERN).access("#oauth2.hasScope('read')")
                .antMatchers(HttpMethod.POST, ROOT_PATTERN).access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PATCH, ROOT_PATTERN).access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PUT, ROOT_PATTERN).access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.DELETE, ROOT_PATTERN).access("#oauth2.hasScope('write')");


    }

    @Bean
    public DefaultTokenServices tokenServices(final TokenStore tokenStore) {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore);
        return tokenServices;
    }

    @Bean
    public TokenStore tokenStore() {
        if (tokenStore == null) {
            tokenStore = new JwtTokenStore(AccessJwtAccessTokenConverter());
        }
        return tokenStore;
    }

    @Bean
    public JwtAccessTokenConverter AccessJwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();

        converter.setVerifierKey(getPublicKeyAsString());
//        converter.setSigningKey(());
        return converter;
    }

    private String getPublicKeyAsString() {
        try {
            return IOUtils.toString(securityProperties.getJwt().getPublicKey().getInputStream(), UTF_8);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

SecurityProperties.java

@ConfigurationProperties("security")
public class SecurityProperties {

    private JwtProperties jwt;

    public JwtProperties getJwt() {
        return jwt;
    }

    public void setJwt(JwtProperties jwt) {
        this.jwt = jwt;
    }

    public static class JwtProperties {

        private Resource keyStore;
        private String keyStorePassword;
        private String keyPairAlias;
        private String keyPairPassword;
        private Resource publicKey;


        public Resource getKeyStore() {
            return keyStore;
        }

        public void setKeyStore(Resource keyStore) {
            this.keyStore = keyStore;
        }

        public String getKeyStorePassword() {
            return keyStorePassword;
        }

        public void setKeyStorePassword(String keyStorePassword) {
            this.keyStorePassword = keyStorePassword;
        }

        public String getKeyPairAlias() {
            return keyPairAlias;
        }

        public void setKeyPairAlias(String keyPairAlias) {
            this.keyPairAlias = keyPairAlias;
        }

        public String getKeyPairPassword() {
            return keyPairPassword;
        }

        public void setKeyPairPassword(String keyPairPassword) {
            this.keyPairPassword = keyPairPassword;
        }
        public Resource getPublicKey() {
            return publicKey;
        }

        public void setPublicKey(Resource publicKey) {
            this.publicKey = publicKey;
        }
    }
}

WebSecurityConfiguration.java

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableConfigurationProperties(value= DataSourceProperties.class)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    private final DataSource dataSource;

    private PasswordEncoder passwordEncoder;
    private UserDetailsService userDetailsService;


    public WebSecurityConfiguration(final DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        if (passwordEncoder == null) {
            passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        }
        return passwordEncoder;
    }

    @Bean
    public UserDetailsService userDetailsService() {
        JdbcDaoImpl jdbcDaoImpl = new JdbcDaoImpl();

        if (userDetailsService == null) {
            userDetailsService = new JdbcDaoImpl();
            ((JdbcDaoImpl) userDetailsService).setDataSource(dataSource);
        }
        return userDetailsService;
}
}

Models/User.java

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "username", unique = true)
    @NotEmpty(message = "Ce champs doit être remplie")
    @Size(min = 6)
    private String username;
    @Column(name = "fullname")
    @NotEmpty(message = "Ce champs doit être remplie")
    @Size(min = 6)
    private String fullname;
    @Column(name = "sexe")
    private String sexe;
    @Column(name = "uuid")
    private String uuid = UUID.randomUUID().toString();
    @Column(name = "tel", unique = true)
    @NotEmpty(message = "Ce champ doit être remplie")
    @Pattern(regexp = "^7[7860][0-9]{7}$", message = "Ce Format de n'est pas valide")
    private String tel;
    @Column(name = "email", unique = true)
    @Email(message = "Ce adresse email n'est pas valide")
    private String email;
    @Column(name = "password")
    @NotEmpty(message = "Ce champ doit être remplie")
    private String password;
    @Column(name = "register_at")
    Date dateRegister = new Date(new Date().getTime());
    @Column(name = "enabled")
    private Boolean enabled = true;
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSexe() {
        return sexe;
    }

    public void setSexe(String sexe) {
        this.sexe = sexe;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getDateRegister() {
        return dateRegister;
    }

    public void setDateRegister(Date dateRegister) {
        this.dateRegister = dateRegister;
    }

    public Boolean getEnabled() {
        return enabled;
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }
}

你知道我的问题所以给我一些解决方案我在这里听原代码Here(我这边我做了一些修改你可以比较一下)

【问题讨论】:

    标签: spring-boot spring-security oauth-2.0 spring-security-oauth2


    【解决方案1】:

    你的问题关键在于AuthorizationServerConfiguration中的JwtAccessTokenConverter配置。它的convertAccessToken()方法负责将认证信息转换成JWT。
    convertAccessToken()方法实际上是由默认值为DefaultAccessTokenConverter的tokenConverter属性执行的

    public class JwtAccessTokenConverter {
    
        private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
        
        @Override
        public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
            return tokenConverter.convertAccessToken(token, authentication);
        }
       
        //...
    }
    

    DefaultAccessTokenConverter 调用 userTokenConverter.convertUserAuthentication() 将 Authentication 转换为 JWT 属性

    public class DefaultAccessTokenConverter {
    
        private UserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter();
    
        public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
            Map<String, Object> response = new HashMap<String, Object>();
            //...
    response.putAll(userTokenConverter.convertUserAuthentication(authentication.getUserAuthentication()));
            //...
            return resposne;
        }
    }
    

    DefaultUserAuthenticationConverter 会将用户名和权限转换为 JWT 属性,这是只有 user_name 和权限才能在您的 jwt 令牌中找到的真正原因。

    public class DefaultUserAuthenticationConverter {
    
        public Map<String, ?> convertUserAuthentication(Authentication authentication) {
            Map<String, Object> response = new LinkedHashMap<String, Object>();
            response.put(USERNAME, authentication.getName());
            if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
                response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
            }
            return response;
        }
    }
    

    现在一切都清楚了,创建自己的 UserAuthenticationConverter 实现并在 AuthorizationServerConfiguration 中进行配置。这是我的一个实现供您参考

    public class SubjectAttributeUserTokenConverter extends DefaultUserAuthenticationConverter {
    
        @Override
        public Map<String, ?> convertUserAuthentication(Authentication authentication) {
            User user = (User) authentication.getPrincipal();
            Map<String, Object> response = new LinkedHashMap<>();
            response.put("name", authentication.getName());
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                Map<String, ?> map = objectMapper.readValue(objectMapper.writeValueAsString(user), Map.class);
                response.putAll(map);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            if (authentication.getAuthorities() != null) {
                response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
            }
            return response;
        }
    }
    
    @EnableAuthorizationServer
    @Configuration
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setKeyPair(keyPair());
            DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
            accessTokenConverter.setUserTokenConverter(new SubjectAttributeUserTokenConverter());
            converter.setAccessTokenConverter(accessTokenConverter);
            return converter;
        }
    }
    

    顺便说一句,spring security oauth2 项目处于维护模式。它的大部分功能如 Oauth2 ResourceServer 和 Oauth2 Client 已经在 Spring Security 中实现了,这是可取的。更多详情请参考OAuth 2.0 Features Matrix

    【讨论】:

      猜你喜欢
      • 2020-03-22
      • 2016-11-17
      • 2020-04-24
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 2016-01-29
      • 1970-01-01
      • 2021-12-04
      相关资源
      最近更新 更多