Spring Security OAuth2 SSO 与自定义提供程序 + 注销

ika*_*ane 5 spring-security single-sign-on spring-boot spring-security-oauth2

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

我想使用我的自定义服务器提供商,它运行良好。

对于客户端,我希望用户在尝试访问客户端站点(例如 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 {

    私有静态最终记录器记录器 = LoggerFactory.getLogger(DemoSsoOauth2ClientApplication.class);

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

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

    公共静态无效主(字符串 [] args){
        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 {

        private static final String CSRF_COOKIE_NAME = "XSRF-TOKEN";
        private static final String 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 request, HttpServletResponse response, FilterChain filterChain)
                        抛出 ServletException,IOException {
                    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
                    如果(CSRF!=空){
                        Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);
                        String token = csrf.getToken();
                        if (cookie == null || token != null
                                && !token.equals(cookie.getValue())) {
                            cookie = 新的 Cookie(CSRF_COOKIE_NAME,令牌);
                            cookie.setPath("/");
                            response.addCookie(cookie);
                        }
                    }
                    filterChain.doFilter(请求,响应);
                }
            };
        }

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

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

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

提前致谢

Jua*_*oza 2

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

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

我在 github 上创建了一个存储库,其中包含一个示例应用程序,该应用程序具有您正在寻找的功能。

请检查一下并告诉我是否对您有帮助。