【问题标题】:Spring Security OAuth2 SSO with Custom provider + logout具有自定义提供程序 + 注销的 Spring Security OAuth2 SSO
【发布时间】:2016-03-26 13:44:08
【问题描述】:

我正在尝试使用 Spring-boot 和 Dave Syer 示例通过 Spring Security Oauth2 实现 sso

我想使用我的 custom server 提供程序,它工作正常。

对于客户端,我希望用户在尝试访问客户端站点(例如 localhost:8080/)时进行身份验证(因此重定向到 OAuth2 url),并在通过身份验证后重定向回 index.html 文件。当用户在 index.html 文件中的链接上时,我还想实现注销。

我想出了以下客户端 sso 客户端:

包 org.ikane;

导入 java.io.IOException;
导入java.security.Principal;
导入 java.util.Arrays;

导入 javax.servlet.Filter;
导入 javax.servlet.FilterChain;
导入 javax.servlet.ServletException;
导入 javax.servlet.http.Cookie;
导入 javax.servlet.http.HttpServletRequest;
导入 javax.servlet.http.HttpServletResponse;

导入 org.apache.commons.lang3.StringUtils;
导入 org.slf4j.Logger;
导入 org.slf4j.LoggerFactory;
导入 org.springframework.boot.CommandLineRunner;
导入 org.springframework.boot.SpringApplication;
导入 org.springframework.boot.autoconfigure.SpringBootApplication;
导入 org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
导入 org.springframework.context.ConfigurableApplicationContext;
导入 org.springframework.core.env.ConfigurableEnvironment;
导入 org.springframework.security.config.annotation.web.builders.HttpSecurity;
导入 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
导入 org.springframework.security.core.Authentication;
导入 org.springframework.security.core.context.SecurityContext;
导入 org.springframework.security.core.context.SecurityContextHolder;
导入 org.springframework.security.web.csrf.CsrfFilter;
导入 org.springframework.security.web.csrf.CsrfToken;
导入 org.springframework.security.web.csrf.CsrfTokenRepository;
导入 org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
导入 org.springframework.stereotype.Component;
导入 org.springframework.stereotype.Controller;
导入 org.springframework.web.bind.annotation.RequestMapping;
导入 org.springframework.web.bind.annotation.ResponseBody;
导入 org.springframework.web.filter.OncePerRequestFilter;
导入 org.springframework.web.util.WebUtils;

@SpringBootApplication
@控制器
公共类 DemoSsoOauth2ClientApplication 实现 CommandLineRunner {

    private static final Logger logger = LoggerFactory.getLogger(DemoSsoOauth2ClientApplication.class);

    @覆盖
    公共无效运行(字符串... arg0)抛出异常{
        SecurityContext securityContext = SecurityContextHolder.getContext();
        尝试 {
            身份验证身份验证 = securityContext.getAuthentication();
            logger.info(authentication.getDetails().toString());

            SecurityContextHolder.clearContext();
        } 捕捉(异常 e){
            logger.error("错误", e);
        }
    }

    公共静态无效主要(字符串[]参数){
        ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoSsoOauth2ClientApplication.class, args);
        ConfigurableEnvironment env = applicationContext.getEnvironment();
        logger.info("\n\thttp://localhost:{}{}\n\tProfiles:{}\n",
                StringUtils.defaultIfEmpty(env.getProperty("server.port"), "8080"),
                StringUtils.defaultIfEmpty(env.getProperty("server.contextPath"), "/"),
                Arrays.toString(env.getActiveProfiles()));
    }

    @RequestMapping(value="/")
    公共字符串主页(){
        返回“索引”;
    }

    @RequestMapping(value="/user")
    @ResponseBody
    公共主要用户(主要用户){
        返回用户;
    }

    /**
     * 设置 OAuth2 单点登录的 OAuthConfiguration 类
     * 配置和与之相关的网络安全。
     */
    @零件
    @控制器
    @EnableOAuth2Sso
    受保护的静态类 OAuthClientConfiguration 扩展 WebSecurityConfigurerAdapter {

        私有静态最终字符串 CSRF_COOKIE_NAME = "XSRF-TOKEN";
        私有静态最终字符串 CSRF_ANGULAR_HEADER_NAME = "X-XSRF-TOKEN";

        @覆盖
        公共无效配置(HttpSecurity http)抛出异常{
            http.antMatcher("/**").authorizeRequests()
                    .antMatchers("/index.html", "/").permitAll().anyRequest()
                    .authenticated().and().csrf().csrfTokenRepository(csrfTokenRepository())
                    .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
        }

        私人过滤器 csrfHeaderFilter() {
            返回新的 OncePerRequestFilter() {

                @覆盖
                protected void doFilterInternal(HttpServletRequest 请求,HttpServletResponse 响应,FilterChain filterChain)
                        抛出 ServletException,IOException {
                    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
                    如果(csrf!= null){
                        Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);
                        字符串令牌 = csrf.getToken();
                        if (cookie == null || token != null
                                && !token.equals(cookie.getValue())) {
                            cookie = 新 Cookie(CSRF_COOKIE_NAME,令牌);
                            cookie.setPath("/");
                            response.addCookie(cookie);
                        }
                    }
                    filterChain.doFilter(request, response);
                }
            };
        }

        /**
         * Angular 在名为“X-XSRF-TOKEN”的自定义标头中发送 CSRF 令牌
         * 而不是 Spring 安全性期望的默认“X-CSRF-TOKEN”。
         * 因此,我们现在告诉 Spring security 期待令牌在
         * “X-XSRF-TOKEN”标头。

* * 此自定义已添加到 csrf() 过滤器中。 * * @返回 */ 私人 CsrfTokenRepository csrfTokenRepository() { HttpSessionCsrfTokenRepository 存储库 = new HttpSessionCsrfTokenRepository(); repository.setHeaderName(CSRF_ANGULAR_HEADER_NAME); 返回存储库; } } }

您可以找到GitHub source。有关如何实现此用例的任何提示?

提前致谢

【问题讨论】:

    标签: spring-security spring-boot single-sign-on spring-security-oauth2


    【解决方案1】:
    • 要让您的客户端应用重定向到授权服务器,只需添加 @EnableOAuth2Sso 上的注释 WebSecurityConfigurerAdapter 和 在您的属性文件中放置正确的 OAuth2 配置(客户端 ID、机密、访问令牌 uri...)。 (我假设您的客户端应用程序也在使用 Spring Boot)

    • 要结束用户会话,您必须重定向到授权服务器中的端点并以编程方式注销,如 this post 所示。

    我创建了一个repository on github,其中包含一个示例应用程序,该应用程序具有您正在寻找的那些功能。

    请检查一下,如果对您有帮助,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-10
      • 2017-05-03
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 2014-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多