首页 > 解决方案 > 带有 OAuth2 和自定义身份验证提供程序的 Spring Boot REST 服务

问题描述

我正在基于spring greeting 示例构建一个 REST 服务。这很好用,我很高兴春天为我节省了时间。今天我试图通过访问令牌和刷新令牌来获得 OAuth2 安全性。当我使用将用户名和密码存储在自己的存储库中的示例时,这很好用。问题是我需要一个自定义身份验证提供程序,因为我需要对第三方系统进行身份验证,该系统将返回 true 或 false 提供用户名和密码。

我确实找到了自定义安全提供程序的示例,但没有使用 AuthorizationServer、ResourceServer、SecurityServer 和自定义授权服务器的从梯度到严重的示例……有人有或可以提供这样的示例吗?

我没有结合所有的例子,因为它们都略有不同......

在此先感谢您的帮助!

问候,

彼得

标签: javaspringrestspring-bootoauth-2.0

解决方案


@Configuration
@EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter{

     @Autowired
        private AuthenticationManager authenticationManager;

        @Autowired
        private UserDetailsService userDetailsService;

        @Bean
        public WebResponseExceptionTranslator loggingExceptionTranslator() {
            return new DefaultWebResponseExceptionTranslator() {
                @Override
                public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
                    // This is the line that prints the stack trace to the log. You can customise this to format the trace etc if you like
                    e.printStackTrace();

                    // Carry on handling the exception
                    ResponseEntity<OAuth2Exception> responseEntity = super.translate(e);
                    HttpHeaders headers = new HttpHeaders();
                    headers.setAll(responseEntity.getHeaders().toSingleValueMap());
                    OAuth2Exception excBody = responseEntity.getBody();
                    return new ResponseEntity<>(excBody, headers, responseEntity.getStatusCode());
                }
            };
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory().withClient("webapp")
                    .secret("{bcrypt}$2a$10$kwz.jnLVLwJOYTAp2r/oG.8tfAN/EC5dK1w5beLgfpuFT6Puprgq.")
                    .authorizedGrantTypes("implicit", "password", "authorization_code", "refresh_toke")
                    .scopes("read", "write").accessTokenValiditySeconds(3600 * 8).refreshTokenValiditySeconds(3600 * 8);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer configurer) throws Exception {
            configurer.tokenKeyAccess("permitAll()")
                    .checkTokenAccess("isAuthenticated()");
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
            enhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter()));

            endpoints
                    .authenticationManager(this.authenticationManager)
                    .accessTokenConverter(jwtAccessTokenConverter())
                    .tokenEnhancer(enhancerChain)
                    .userDetailsService(userDetailsService)
                    .exceptionTranslator(loggingExceptionTranslator());
        }


        @Bean
        public TokenEnhancer tokenEnhancer() {
            return (accessToken, authentication) -> {
                MyPrincipal userDetails = (MyPrincipal)userDetailsService.loadUserByUsername(authentication.getName());
                Map<String, Object> additionalInfor = new HashMap<>();
                additionalInfor.put("accountName", userDetails.getUsername());
                additionalInfor.put("authorities", userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
                ((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(additionalInfor);
                return accessToken;
            };
        }

        @Bean
        UserAuthenticationConverter userAuthenticationConverter() {
            DefaultUserAuthenticationConverter converter = new DefaultUserAuthenticationConverter();
            converter.setUserDetailsService(userDetailsService);
            return converter;
        }

        @Bean
        AccessTokenConverter accessTokenConverter() {
            DefaultAccessTokenConverter converter = new DefaultAccessTokenConverter();
            converter.setUserTokenConverter(userAuthenticationConverter());
            return converter;
        }

        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setAccessTokenConverter(accessTokenConverter());
            converter.setSigningKey("123");
            return converter;
        }

        @Bean
        public FilterRegistrationBean corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowCredentials(true);
            configuration.addAllowedOrigin("*");
            configuration.addAllowedHeader("*");
            configuration.addAllowedMethod("*");
            source.registerCorsConfiguration("/**", configuration);
            FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
            bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
            return bean;
        }


}

推荐阅读