如何限制到特定域以使用 Spring-Boot 和 OAuth2 登录 [英] How to restrict to a specific domain to login with Spring-Boot and OAuth2
问题描述
我已成功使用 Spring Boot 和 Google 进行 OAuth2 登录,但我想将登录限制在特定域(我们使用的是 Google Apps for Work).
I have successfully done a OAuth2 login with spring boot and Google, but I'd like to restrict logins to a specific domain (we're using Google Apps for Work).
我认为我应该通过扩展类 OAuth2ClientAuthenticationProcessingFilter(如指定的在此线程中),但我不知道该怎么做.
I think that I should handle by extending class OAuth2ClientAuthenticationProcessingFilter (as specified in this thread), but I'm not sure how to do that.
基本上,我想使用 Google OAuth 2.0 作为身份提供者,但必须只接受公司用户 (@company.com).
Basically, I'd like to use Google OAuth 2.0 as the identity provider, but only company users (@company.com) must be accepted.
推荐答案
根据Stéphane的建议,我来到了这个教程,并最终实现了这一点,它适用于我的 Google+ 个人资料:
According to Stéphane suggestion, I came to this tutorial, and finally implemented this, which works for me with a Google+ profile:
@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 的条目:
My application.yml file contains the following entries regarding 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+ 个人资料时,地图中提供的资源服务器响应包含域条目.我只是将这个值与配置的允许域进行了比较.
When working with a Google+ profile, the resource server response provided in the map, contains an entry for domain. I just compared this value with configured allowed domains.
希望这会有所帮助.
更新:2019 年 3 月 7 日,Google 将弃用 Google+ API.如果您像我一样,就会收到一封来自 Google 的电子邮件,建议您更新您的软件.在我们的例子中,url https://www.googleapis.com/plus/v1/人/我,将被弃用.所以,我在这里发布我更新的配置(使用 Spring Boot 1.3.5 构建).
Update: On March 7th 2019, Google is deprecating Google+ APIs. If you're like me, you'll have received an email from Google suggesting to update your software. In our case, the url https://www.googleapis.com/plus/v1/people/me, will be deprecated. So, I'm posting here my updated configuration (build with 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 中进行细微更改,因为属性域已更改其名称.因此,您需要替换该行:
Please note that minor change must be done in you WebSecurityConfigurerAdapter as the attribute domain has changed its name. So you'll need to replace the line:
private static final String GOOGLE_PLUS_DOMAIN_ATTRIBUTE = "domain";
private static final String GOOGLE_PLUS_DOMAIN_ATTRIBUTE = "domain";
与
private static final String HOSTED_DOMAIN_ATTRIBUTE = "hd";
private static final String HOSTED_DOMAIN_ATTRIBUTE = "hd";
这篇关于如何限制到特定域以使用 Spring-Boot 和 OAuth2 登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!