我有一个用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”;
这是应对这种情况的最佳方法。