gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:31:45 25 4
gpt4 key购买 nike

我正在开发一个Web应用程序,以公开由OAuth 2.0保护的许多RESTful服务。这是计划的体系结构:

1- OAuth授权提供者: WSO2身份服务器(IS)

2- OAuth资源服务器: Java Web应用程序,使用以下技术:

  • Jersey(用于实现和公开Web服务)
  • Spring Security(用于实现OAuth资源服务器部分)

  • 我已经看到了几个有关如何使用WSO2 IS作为授权服务器+ WSO2 ESB作为资源服务器来保护RESTful服务的示例( ex1ex2ex3等)。这不是我所需要的。

    不幸的是,授权服务器和资源服务器之间的交互超出了 OAuth2 RFC的范围。因此,我找不到更多的外观。

    这是我的问题:
  • 如何配置spring安全性以充当资源服务器来验证由外部OAuth提供者发出的访问 token (例如WSO2 IS)?
  • 资源服务器应如何识别给定访问 token 的范围?
  • 如何识别从WSO2 IS获得访问 token 的资源所有者?

  • 谢谢

    最佳答案

    经过研究后,我想出了方法。该解决方案分为两个主要部分: WSO2 IS配置资源服务器配置

    基本方案如下:

    1-客户端(例如,移动应用程序)通过向资源服务器(在我的情况下为Java Web应用程序)发送请求来消耗安全资源(例如,Web服务)。

    2-资源服务器验证请求中的“授权” header 并提取访问 token 。

    3-资源服务器通过将访问 token 发送到授权服务器(WSO2 IS)来验证访问 token 。

    4-授权服务器以验证响应进行响应。

    5-资源服务器验证响应并决定是授予还是拒绝对所请求资源的访问。

    在我的演示中,我使用了WSO2 IS 5.0.0和Spring security 3.1.0。

    1- WSO2 IS配置

    WSO2 IS将充当授权服务器。因此,应将其配置为支持OAuth 2.0。为此,应添加新的服务提供商并将其配置如下:

    (a)登录到WSO2 IS管理控制台。

    (b)添加一个新的服务提供商,并为其提供名称和描述。

    (c)在入站身份验证配置下 >> OAuth/OpenID Connect配置 >>单击配置

    (d)如以下屏幕截图所示配置OAuth 2.0提供程序,然后单击添加。我们需要密码授予类型,它映射到资源所有者密码凭证授予类型。最适合我的情况(确保Web服务安全)。

    (e)在 OAuth/OpenID Connect配置下,您会找到 OAuth客户端 key OAuth客户端 key 。它们与用户名,密码和范围一起使用以生成访问 token 。

    2-资源服务器配置

    如前所述,该演示Java Web应用程序将同时充当资源服务器和客户端。为了充当资源服务器,Spring安全需要知道如何验证访问 token 。因此,应提供 token 服务实现。

    (a)将spring配置为充当资源服务器。这是一个示例配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.1.xsd
    http://www.springframework.org/schema/security/oauth2
    http://www.springframework.org/schema/security/spring-security-oauth2.xsd">

    <bean id="tokenServices" class="com.example.security.oauth2.wso2.TokenServiceWSO2" />

    <bean id="authenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />

    <security:authentication-manager alias="authenticationManager" />

    <oauth2:resource-server id="resourcesServerFilter" token-services-ref="tokenServices" />

    <security:http pattern="/services/**" create-session="stateless" entry-point-ref="authenticationEntryPoint" >
    <security:anonymous enabled="false" />
    <security:custom-filter ref="resourcesServerFilter" before="PRE_AUTH_FILTER" />
    <security:intercept-url pattern="/services/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    </security:http>
    </beans>

    在这里,配置了使用 token 服务实现 TokenServiceWSO2 资源服务器资源服务器标记实际上已转换为安全过滤器。将拦截模式添加到“/services/**”,并将资源服务器过滤器添加到链。

    (b)实现OAuth 2.0 token 服务 ResourceServerTokenServices 。该实现将以访问 token 作为输入,将其传递给WSO2 IS公开的 OAuth2TokenValidationService 服务,验证响应并返回包含有关 token 的发行者,有效性,范围,相应的JWT token 的基本数据的处理对象。 。
    public class TokenServiceWSO2 implements ResourceServerTokenServices {

    @Autowired
    TokenValidatorWSO2 tokenValidatorWSO2;

    public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException {

    try {
    TokenValidationResponse validationResponse = tokenValidatorWSO2.validateAccessToken(accessToken);
    OAuth2Request oAuth2Request = new OAuth2Request(null, null, null, true, validationResponse.getScope(), null, null, null,null);
    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(validationResponse.getAuthorizedUserIdentifier(), null, null);
    OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
    return oAuth2Authentication;
    } catch (ApplicationException ex) {
    // Handle exception
    }
    }

    public OAuth2AccessToken readAccessToken(String accessToken) {
    // TODO Add implementation
    }

    }

    TokenValidatorWSO2 类实现了调用WSO2 IS的Web服务的逻辑 OAuth2TokenValidationService
    @Component
    public class TokenValidatorWSO2 implements OAuth2TokenValidator{

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

    @Value("${server_url}")
    private String serverUrl;

    @Value("${validation_service_name}")
    private String validationServiceName;

    @Value("${comsumer_key}")
    private String consumerKey;

    @Value("${admin_username}")
    private String adminUsername;

    @Value("${admin_password}")
    private String adminPassword;

    private OAuth2TokenValidationServiceStub stub;

    private static final int TIMEOUT_IN_MILLIS = 15 * 60 * 1000;

    public TokenValidationResponse validateAccessToken(String accessToken) throws ApplicationException {
    logger.debug("validateAccessToken(String) - start");

    if(stub == null) {
    initializeValidationService();
    }

    OAuth2TokenValidationRequestDTO oauthRequest;
    TokenValidationResponse validationResponse;
    OAuth2TokenValidationRequestDTO_OAuth2AccessToken oAuth2AccessToken;

    try {
    oauthRequest = new OAuth2TokenValidationRequestDTO();
    oAuth2AccessToken = new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
    oAuth2AccessToken.setIdentifier(accessToken);
    oAuth2AccessToken.setTokenType("bearer");
    oauthRequest.setAccessToken(oAuth2AccessToken);
    OAuth2TokenValidationResponseDTO response = stub.validate(oauthRequest);

    if(!response.getValid()) {
    throw new ApplicationException("Invalid access token");
    }

    validationResponse = new TokenValidationResponse();
    validationResponse.setAuthorizedUserIdentifier(response.getAuthorizedUser());
    validationResponse.setJwtToken(response.getAuthorizationContextToken().getTokenString());
    validationResponse.setScope(new LinkedHashSet<String>(Arrays.asList(response.getScope())));
    validationResponse.setValid(response.getValid());

    } catch(Exception ex) {
    logger.error("validateAccessToken() - Error when validating WSO2 token, Exception: {}", ex);
    }

    logger.debug("validateAccessToken(String) - end");
    return validationResponse;
    }

    private void initializeValidationService() throws ApplicationException {
    try {
    String serviceURL = serverUrl + validationServiceName;
    stub = new OAuth2TokenValidationServiceStub(null, serviceURL);
    CarbonUtils.setBasicAccessSecurityHeaders(adminUsername, adminPassword, true, stub._getServiceClient());
    ServiceClient client = stub._getServiceClient();
    Options options = client.getOptions();
    options.setTimeOutInMilliSeconds(TIMEOUT_IN_MILLIS);
    options.setProperty(HTTPConstants.SO_TIMEOUT, TIMEOUT_IN_MILLIS);
    options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, TIMEOUT_IN_MILLIS);
    options.setCallTransportCleanup(true);
    options.setManageSession(true);
    } catch(AxisFault ex) {
    // Handle exception
    }
    }
    }

    TokenValidationResponse 类保存 token 验证响应中返回的基本数据。
    public class TokenValidationResponse {

    private String jwtToken;
    private boolean valid;
    private Set<String> scope;
    private String authorizedUserIdentifier;

    public String getJwtToken() {
    return jwtToken;
    }

    public void setJwtToken(String jwtToken) {
    this.jwtToken = jwtToken;
    }

    public boolean isValid() {
    return valid;
    }

    public void setValid(boolean valid) {
    this.valid = valid;
    }

    public Set<String> getScope() {
    return scope;
    }

    public void setScope(Set<String> scope) {
    this.scope = scope;
    }

    public String getAuthorizedUserIdentifier() {
    return authorizedUserIdentifier;
    }

    public void setAuthorizedUserIdentifier(String authorizedUserIdentifier) {
    this.authorizedUserIdentifier = authorizedUserIdentifier;
    }
    }

    3-客户端应用程序配置

    最后一步是配置要由OAuth 2.0保护的资源。基本上,将Web服务配置为使用根URL路径“/services/**”保护。在演示中,我使用了Jersey。

    4-测试客户端应用程序

    最后一步是使用 protected Web服务。这是通过将 授权 header 添加到带有值“ ”的请求中来完成的,例如“ 承载7fbd71c5b28fdf0bdb922b07915c4d5 ”。

    P.S.所描述的示例仅用于说明目的。它可能缺少某些实现,异常处理等。

    关于java - 使用Spring Security + WSO2身份服务器的OAuth 2.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27551358/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com