根据Stéphane的建议,我来到了这个tutorial https://spring.io/guides/tutorials/spring-boot-oauth2/,最后实现了这个,它适用于我的 Google+ 个人资料:
@Configuration
@EnableOAuth2Sso
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String GOOGLE_PLUS_DOMAIN_ATTRIBUTE = "domain";
private static final String CSRF_COOKIE_NAME = "XSRF-TOKEN";
private static final String CSRF_HEADER_NAME = "X-XSRF-TOKEN";
@Bean
public AuthoritiesExtractor authoritiesExtractor(
@Value("#{'${security.allowed-domains}'.split(',')}") final List<String> allowedDomains) {
return new AuthoritiesExtractor() {
@Override
public List<GrantedAuthority> extractAuthorities(final Map<String, Object> map) {
if (map != null && map.containsKey(GOOGLE_PLUS_DOMAIN_ATTRIBUTE)) {
final String domain = (String) map.get(GOOGLE_PLUS_DOMAIN_ATTRIBUTE);
if (!allowedDomains.contains(domain)) {
throw new BadCredentialsException("Not an allowed domain");
}
return AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");
}
return null;
}
};
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
// @formatter:off
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/logout", "/api/mappings/**", "/public/**").permitAll()
.anyRequest().hasAuthority("ROLE_USER")
.and().logout().logoutUrl("/api/logout").logoutSuccessUrl("/logout")
.and().csrf().csrfTokenRepository(csrfTokenRepository()).ignoringAntMatchers("/api/mappings/**")
.and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
// @formatter:on
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException {
final CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);
final String token = csrf.getToken();
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie(CSRF_COOKIE_NAME, token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
final HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName(CSRF_HEADER_NAME);
return repository;
}
}
我的 application.yml 文件包含以下有关 oauth 的条目:
security:
oauth2:
client:
access-token-uri: https://www.googleapis.com/oauth2/v3/token
user-authorization-uri: https://accounts.google.com/o/oauth2/auth
client-authentication-scheme: form
scope: profile,email
resource:
user-info-uri: https://www.googleapis.com/plus/v1/people/me
prefer-token-info: false
使用 Google+ 个人资料时,地图中提供的资源服务器响应包含域条目。我只是将此值与配置的允许域进行比较。
希望这可以帮助。
更新:2019 年 3 月 7 日,Google 将弃用 Google+ API。如果您像我一样,您将会收到一封来自 Google 的电子邮件,建议更新您的软件。在我们的例子中,网址https://www.googleapis.com/plus/v1/people/me https://www.googleapis.com/plus/v1/people/me,将被弃用。因此,我在这里发布我更新的配置(使用 Spring Boot 1.3.5 构建)。
security:
oauth2:
client:
clientId: *your client id from Google*
clientSecret: *your client secret from Google*
accessTokenUri: https://www.googleapis.com/oauth2/v4/token
userAuthorizationUri: https://accounts.google.com/o/oauth2/v2/auth
clientAuthenticationScheme: form
scope:
- email
- profile
resource:
userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
preferTokenInfo: false
# Comma-separated list of domains
allowed-domains: *your allowed domains*
请注意,由于属性域已更改其名称,因此必须在 WebSecurityConfigurerAdapter 中进行细微更改。所以你需要更换该行:
私有静态最终字符串GOOGLE_PLUS_DOMAIN_ATTRIBUTE =“域”;
with
私有静态最终字符串HOSTED_DOMAIN_ATTRIBUTE =“hd”;