如何结合使用Spring Boot Security OAuth2和基本身份验证

时间:2019-09-29 21:01:06

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

在我们的项目中,如果用户使用承载令牌调用api,我们将使用oauth2身份验证。

如果用户使用基本身份验证调用api,则可以为基本身份验证添加第二个securityConfig。 但是我如何才能针对oauth2提供程序对这个basicAuth用户进行身份验证?

我尝试使用customAuthenticationProvider通过restTemplate获取访问令牌,这可行。

还有其他解决方法吗?

这是我的SecurityConfig:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Value("${security.oauth2.resource.id}")
        private String resourceId;

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

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                    .authorizeRequests()
                    .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                    .antMatchers("/api/**").authenticated();
        }
    }

    @Order(2)
    @Configuration
    protected static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

        private final RestTemplateBuilder restTemplateBuilder;

        @Value("${oauth2.issuer}")
        private String issuer;

        @Autowired
        public WebSecurityConfiguration(RestTemplateBuilder restTemplateBuilder) {
            this.restTemplateBuilder = restTemplateBuilder;
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.anonymous().disable()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                    .requestMatcher(new BasicRequestMatcher())
                    .authorizeRequests()
                    .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                    .antMatchers("/api/**").authenticated()
                    .and()
                    .httpBasic();
        }

        private static class BasicRequestMatcher implements RequestMatcher {
            @Override
            public boolean matches(HttpServletRequest request) {
                String auth = request.getHeader("Authorization");
                return (auth != null && auth.startsWith("Basic"));
            }
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(new OauthAuthenticationProvider(restTemplateBuilder, issuer));
        }
    }
}

这是CustomAuthenticationProvider

@Slf4j
public class OauthAuthenticationProvider implements AuthenticationProvider {

    private final RestTemplateBuilder restTemplateBuilder;
    private String issuer;

    OauthAuthenticationProvider(RestTemplateBuilder restTemplateBuilder, String issuer) {
        this.restTemplateBuilder = restTemplateBuilder;
        this.issuer = issuer;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> authorizationParameters = new LinkedMultiValueMap<>();
        authorizationParameters.add("username", authentication.getPrincipal().toString());
        authorizationParameters.add("password", authentication.getCredentials().toString());
        authorizationParameters.add("client_id", "client-id");
        authorizationParameters.add("client_secret", "client-secret");
        authorizationParameters.add("grant_type", "password");

        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(authorizationParameters, headers);
        final RestTemplate restTemplate = restTemplateBuilder.rootUri(issuer).build();

        try {

            final ResponseEntity<DefaultOAuth2AccessToken> tokenResponseEntity = restTemplate.postForEntity("/protocol/openid-connect/token", request, DefaultOAuth2AccessToken.class, Collections.emptyMap());
            if (tokenResponseEntity.getBody() != null) {
                return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", Collections.emptyList());
            }
        } catch (HttpClientErrorException e) {
            log.info(e.getMessage(), e);
            throw e;
        }

        return null;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}

0 个答案:

没有答案