REST API由外部OAuth保护-Angular(7)应用

时间:2019-04-03 09:14:11

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

我有一个用Spring构建的Rest APi,除一个端点外,所有端点都是公共的;

public class APISecurityConfiguration extends WebSecurityConfigurerAdapter {

private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
        new AntPathRequestMatcher("/api/home/nest/**")
      );

private static final RequestMatcher UN_PROTECTED_API_URLS = new NegatedRequestMatcher(PROTECTED_URLS);

@Autowired
private ClientRegistrationRepository clientRegistrationRepository;

/*
 * (non-Javadoc)
 * 
 * @see org.springframework.security.config.annotation.web.configuration.
 * WebSecurityConfigurerAdapter#configure(org.springframework.security.config.
 * annotation.web.builders.HttpSecurity)
 */
@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
     http
        .cors()
        .and()
        .csrf().disable()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers("/api/home/*").permitAll()
        .requestMatchers(PROTECTED_URLS).authenticated()
        .and()
        .oauth2Login()
        .tokenEndpoint()
        .accessTokenResponseClient(accessTokenResponseClient())
        .and()
        .userInfoEndpoint().userService(new NestUserDetailsService());

    // @formatter:on
}

@Bean
public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient() {
    DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
    accessTokenResponseClient.setRequestEntityConverter(new NestRequestEntityConverter());

    OAuth2AccessTokenResponseHttpMessageConverter tokenResponseHttpMessageConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
    tokenResponseHttpMessageConverter.setTokenResponseConverter(new NestTokenResponseConverter());
    RestTemplate restTemplate = new RestTemplate(
            Arrays.asList(new FormHttpMessageConverter(), tokenResponseHttpMessageConverter));
    restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());

    accessTokenResponseClient.setRestOperations(restTemplate);
    return accessTokenResponseClient;
}

static class NestRequestEntityConverter
        implements Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>> {

    private OAuth2AuthorizationCodeGrantRequestEntityConverter defaultConverter;

    public NestRequestEntityConverter() {
        defaultConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter();
    }

    @Override
    public RequestEntity<?> convert(OAuth2AuthorizationCodeGrantRequest source) {
        RequestEntity<?> oAuth2AuthorizationCodeGrantRequestEntity = defaultConverter.convert(source);
        MultiValueMap<String, String> params = (MultiValueMap<String, String>) oAuth2AuthorizationCodeGrantRequestEntity
                .getBody();

        params.add("client_id", source.getClientRegistration().getClientId());
        params.add("client_secret", source.getClientRegistration().getClientSecret());

        return oAuth2AuthorizationCodeGrantRequestEntity;
    }

}

static class NestTokenResponseConverter implements Converter<Map<String, String>, OAuth2AccessTokenResponse> {

    @Override
    public OAuth2AccessTokenResponse convert(Map<String, String> tokenResponseParameters) {

        log.debug("TOKEN RESPONSE {}", tokenResponseParameters);
        String accessToken = tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN);
        long expiresIn = Long.valueOf(tokenResponseParameters.get(OAuth2ParameterNames.EXPIRES_IN));

        OAuth2AccessToken.TokenType accessTokenType = OAuth2AccessToken.TokenType.BEARER;

        return OAuth2AccessTokenResponse.withToken(accessToken).tokenType(accessTokenType).expiresIn(expiresIn)
                .build();
    }

}

static class NestUserDetailsService extends DefaultOAuth2UserService {

    private Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter = new OAuth2UserRequestEntityConverter();

    private RestOperations restOperations;

    public NestUserDetailsService() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
        this.restOperations = restTemplate;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService#
     * loadUser(org.springframework.security.oauth2.client.userinfo.
     * OAuth2UserRequest)
     */
    @Override
    public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {
        String auth = "Bearer " + oAuth2UserRequest.getAccessToken().getTokenValue(); // Update with your token

        RequestEntity<?> request = this.requestEntityConverter.convert(oAuth2UserRequest);


        ResponseEntity<Nest> response;
        NestUser user = null;
        try {
            response = this.restOperations.exchange(request, Nest.class);
            log.debug("RESPONSE {}", response.getBody());
            user = new NestUser(response.getBody());
        } catch (OAuth2AuthorizationException ex) {

        }
        //log.debug("USER ", user);
        return user;
    }

}

@Data
@ToString
static class NestUser implements OAuth2User {



    private Nest nest;
    public NestUser(Nest nest) {
        this.nest = nest;

    }

    @Override
    public String getName() {
        // TODO Auto-generated method stub
        return this.nest.getMetadata().getUserId();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = Collections
                .unmodifiableCollection(Arrays.asList(new SimpleGrantedAuthority("USER")));
        return authorities;
    }

    @Override
    public Map<String, Object> getAttributes() {
        // TODO Auto-generated method stub
        return null;
    }

}   

}

身份验证工作正常,我获得了令牌,但是调用该流的端点从未被调用。

还请提出是否有更好的方法来处理此问题。

在我的Angular应用中,我使用

调用身份验证

window.location.href =“ http://localhost/api/home/nest/sync”;

这是应对这种情况的最佳方法。

0 个答案:

没有答案