如何限制到特定域以使用 Spring-Boot 和 OAuth2 登录 [英] How to restrict to a specific domain to login with Spring-Boot and OAuth2

查看:30
本文介绍了如何限制到特定域以使用 Spring-Boot 和 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆