带有 WSO2 身份服务器的 Spring Cloud Security

Posted

技术标签:

【中文标题】带有 WSO2 身份服务器的 Spring Cloud Security【英文标题】:Spring Cloud Security with WSO2 Identity Server 【发布时间】:2015-07-19 17:56:51 【问题描述】:

我正在尝试实现一个 spring-boot-web 应用程序,该应用程序使用 spring-cloud-security 和外部本地身份验证服务器 (WSO2 Identity Server) 进行保护。我们正在使用 OAuth2 OpenID Connect(JWT 令牌)。

对于 /oauth2/authorize 请求,我的应用程序将重定向到 WSO2 服务器,但是当它尝试将 authentication_code 转换为 access_token 时失败。 spring-boot 报告 401 认证错误。

我相信这是因为 oauth2/token 端点需要基本身份验证。

有人可以指导我如何使 /oauth2/token 请求使用带有 spring-cloud-security 的基本身份验证标头吗?

这是我的 application.yml

spring:
  oauth2:
    sso:
      home:
        secure: false
        path: /,/**/*.html
    client:
      accessTokenUri: https://URI:9443/oauth2/token
      userAuthorizationUri: https://URI:9443/oauth2/authorize
      clientId: id
      clientSecret: secret
      scope: openid
      clientAuthenticationScheme: header
    resource:
      userInfoUri: https://URI:9443/oauth2/userinfo?schema=openid

这是我的简单 application.java

package demo;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.security.oauth2.sso.EnableOAuth2Sso;
import org.springframework.cloud.security.oauth2.sso.OAuth2SsoConfigurerAdapter;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;

@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class SpringOauth2WithWso2Application 

    public static void main(String[] args) 
        SpringApplication.run(SpringOauth2WithWso2Application.class, args);
    

    @Configuration
    protected static class SecurityConfiguration extends OAuth2SsoConfigurerAdapter 

        @Override
          public void match(RequestMatchers matchers) 
            matchers.anyRequest();
          

          @Override
          public void configure(HttpSecurity http) throws Exception 
            http.authorizeRequests().antMatchers("/index.html", "/home.html", "/")
                .permitAll().anyRequest().authenticated().and().csrf()
                .csrfTokenRepository(csrfTokenRepository()).and()
                .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
          



        private Filter csrfHeaderFilter() 
            return new OncePerRequestFilter() 
                @Override
                protected void doFilterInternal(HttpServletRequest request,
                        HttpServletResponse response, FilterChain filterChain)
                        throws ServletException, IOException 
                    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                            .getName());
                    if (csrf != null) 
                        Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                        String token = csrf.getToken();
                        if (cookie == null || token != null
                                && !token.equals(cookie.getValue())) 
                            cookie = new Cookie("XSRF-TOKEN", token);
                            cookie.setPath("/");
                            response.addCookie(cookie);
                        
                    
                    filterChain.doFilter(request, response);
                
            ;
        

        private CsrfTokenRepository csrfTokenRepository() 
            HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
            repository.setHeaderName("X-XSRF-TOKEN");
            return repository;
        
    



【问题讨论】:

原来错误是由于 wso2 身份服务器使用自签名证书造成的。我们通过在 spring-boot 启动命令中添加 -Djavax.net.debug=ssl 来诊断它。我们通过将 WSO2 服务器的公共证书添加到 spring-boot 应用程序的 java 信任库来解决此问题。问题解决了。 值得发布一个完整的答案,否则如果他们希望使用它来帮助他们将 Spring Cloud Security(尤其是 Spring Security OAuth2)与 WSO2 IS 集成,这篇文章最终会浪费人们的时间。例如,如果您希望将 Spring Security OAuth2 与 WSO2 IS 一起使用,则此问题/线程肯定具有相关性:github.com/spring-cloud/spring-cloud-security/issues/63(请注意在尝试访问用户身份时需要从承载更改为承载,这是链中的最后一步) .也可以将标题(带有 WSO2 IS 的 Spring Cloud Security)更改为不那么通用的名称。 【参考方案1】:

虽然已经提到需要将 WSO2 IS 证书添加到 Java 证书存储中作为一种解决方案,但它可以帮助任何人执行所需的步骤,以及设置 mitmproxy 以便检查流量通过模板项目在此处记录:https://github.com/nicodewet/template-spring-boot-oauth2-wso2-is

【讨论】:

以上是关于带有 WSO2 身份服务器的 Spring Cloud Security的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Security + WSO2 身份服务器的 OAuth 2.0

Spring SAML 与 WSO2 身份服务器集成,无法识别 SAML 消息

使用 OKTA 的 WSO2 最终用户身份验证

WSO2 Api 管理器与身份服务器

在 WSO2 身份服务器日志中打印用户的 IP 地址

wso2 spring security saml 无状态集成