如何在Spring Boot SSO + zuul中从OAuth令牌检索范围

马兹汗

我正在尝试使用Spring boot SSO + Zuul创建一个简单的API网关。我需要将OAuth范围转换为标头,其他后端服务将进一步使用这些标头来基于标头执行RBAC。

我正在使用这个CustomOAuth2TokenRelayFilter,它将在发送到后端之前基本上设置标头。我的问题是如何从当前令牌中获取作用域。OAuth2AuthenticationDetails类确实提供令牌值,但不提供范围。

我不确定如何在其中获取范围。

以下是自定义Zuul过滤器,该过滤器主要来自https://github.com/spring-cloud/spring-cloud-security/blob/master/spring-cloud-security/src/main/java/org/springframework/cloud /security/oauth2/proxy/OAuth2TokenRelayFilter.java

    import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.stereotype.Component;

@Component
    public class CustomOAuth2TokenRelayFilter extends ZuulFilter {

        private static Logger LOGGER = LoggerFactory.getLogger(CustomOAuth2TokenRelayFilter.class);

        private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
        private static final String TOKEN_TYPE = "TOKEN_TYPE";

        private OAuth2RestOperations restTemplate;


        public void setRestTemplate(OAuth2RestOperations restTemplate) {
            this.restTemplate = restTemplate;
        }


        @Override
        public int filterOrder() {
            return 1;
        }

        @Override
        public String filterType() {
            return "pre";
        }

        @Override
        public boolean shouldFilter() {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();

            if (auth instanceof OAuth2Authentication) {
                Object details = auth.getDetails();
                if (details instanceof OAuth2AuthenticationDetails) {
                    OAuth2AuthenticationDetails oauth = (OAuth2AuthenticationDetails) details;
                    RequestContext ctx = RequestContext.getCurrentContext();

                    LOGGER.debug ("role " + auth.getAuthorities());

                    LOGGER.debug("scope", ctx.get("scope")); // How do I obtain the scope ??


                    ctx.set(ACCESS_TOKEN, oauth.getTokenValue());
                    ctx.set(TOKEN_TYPE, oauth.getTokenType()==null ? "Bearer" : oauth.getTokenType());
                    return true;
                }
            }
            return false;
        }

        @Override
        public Object run() {
            RequestContext ctx = RequestContext.getCurrentContext();
            ctx.addZuulRequestHeader("x-pp-user", ctx.get(TOKEN_TYPE) + " " + getAccessToken(ctx));
            return null;
        }

        private String getAccessToken(RequestContext ctx) {
            String value = (String) ctx.get(ACCESS_TOKEN);
            if (restTemplate != null) {
                // In case it needs to be refreshed
                OAuth2Authentication auth = (OAuth2Authentication) SecurityContextHolder
                        .getContext().getAuthentication();
                if (restTemplate.getResource().getClientId()
                        .equals(auth.getOAuth2Request().getClientId())) {
                    try {
                        value = restTemplate.getAccessToken().getValue();
                    }
                    catch (Exception e) {
                        // Quite possibly a UserRedirectRequiredException, but the caller
                        // probably doesn't know how to handle it, otherwise they wouldn't be
                        // using this filter, so we rethrow as an authentication exception
                        throw new BadCredentialsException("Cannot obtain valid access token");
                    }
                }
            }
            return value;
        }

    }
里卡多·里波利斯(Riccardo Lippolis)

您可以将OAuth2ClientContext注入到过滤器中,并用于oAuth2ClientContext.getAccessToken().getScope()检索范围。

OAuth2ClientContext是一个会话范围的Bean,其中包含当前访问令牌和保留状态。

因此,如果我们将其应用于您的示例,它将看起来像这样:

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.stereotype.Component;

@Component
public class CustomOAuth2TokenRelayFilter extends ZuulFilter {

    private static Logger LOGGER = LoggerFactory.getLogger(CustomOAuth2TokenRelayFilter.class);

    private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
    private static final String TOKEN_TYPE = "TOKEN_TYPE";

    private OAuth2RestOperations restTemplate;

    @Autowired
    private OAuth2ClientContext oAuth2ClientContext;

    public void setRestTemplate(OAuth2RestOperations restTemplate) {
        this.restTemplate = restTemplate;
    }


    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public boolean shouldFilter() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (auth instanceof OAuth2Authentication) {
            Object details = auth.getDetails();
            if (details instanceof OAuth2AuthenticationDetails) {
                OAuth2AuthenticationDetails oauth = (OAuth2AuthenticationDetails) details;
                RequestContext ctx = RequestContext.getCurrentContext();

                LOGGER.debug ("role " + auth.getAuthorities());

                LOGGER.debug("scope" + oAuth2ClientContext.getAccessToken().getScope());

                ctx.set(ACCESS_TOKEN, oauth.getTokenValue());
                ctx.set(TOKEN_TYPE, oauth.getTokenType()==null ? "Bearer" : oauth.getTokenType());
                return true;
            }
        }
        return false;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.addZuulRequestHeader("x-pp-user", ctx.get(TOKEN_TYPE) + " " + getAccessToken(ctx));
        return null;
    }

    private String getAccessToken(RequestContext ctx) {
        String value = (String) ctx.get(ACCESS_TOKEN);
        if (restTemplate != null) {
            // In case it needs to be refreshed
            OAuth2Authentication auth = (OAuth2Authentication) SecurityContextHolder
                    .getContext().getAuthentication();
            if (restTemplate.getResource().getClientId()
                    .equals(auth.getOAuth2Request().getClientId())) {
                try {
                    value = restTemplate.getAccessToken().getValue();
                }
                catch (Exception e) {
                    // Quite possibly a UserRedirectRequiredException, but the caller
                    // probably doesn't know how to handle it, otherwise they wouldn't be
                    // using this filter, so we rethrow as an authentication exception
                    throw new BadCredentialsException("Cannot obtain valid access token");
                }
            }
        }
        return value;
    }

}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在Spring Boot SSO + zuul中从OAuth令牌检索范围

来自分类Dev

如何在Disqus中查找SSO用户?

来自分类Dev

如何在Disqus中查找SSO用户?

来自分类Dev

如何在Android应用中实现SSO

来自分类Dev

如何在Spring Boot中禁用ErrorPageFilter?

来自分类Dev

如何在Spring Boot中添加UrlRewriteFilter

来自分类Dev

如何在spring boot中查询关系?

来自分类Dev

如何在Spring Boot中覆盖Spring Security默认配置

来自分类Dev

如何在Spring Boot中替换Spring ApplicationContext

来自分类Dev

SSO Spring kerberos中的注销功能

来自分类Dev

spring-boot 1.3-M5 oauth2 SSO不能与spring-session一起使用吗?

来自分类Dev

如何在SAML2.0中使用SSO

来自分类Dev

如何在Vaadin 14中处理SSO重定向

来自分类Dev

如何在 Spring Boot 中使用预定义的令牌绕过 Oauth2 身份验证?

来自分类Dev

如何在Spring Boot上验证查询参数的范围

来自分类Dev

如何在 Spring Boot 应用程序中从 Api 网关(Zuul)调用外部服务(非 MSA)

来自分类Dev

如何在Spring Boot中创建Tcp Connection以接受连接?

来自分类Dev

如何在Spring Boot中配置邮件通道?

来自分类Dev

如何在Eclipse tomcat中运行Spring Boot App?

来自分类Dev

如何在Spring Boot中摆脱JpaRepository接口

来自分类Dev

如何在Spring Boot中关闭调试日志消息

来自分类Dev

如何在Spring Boot中模拟db连接以进行测试?

来自分类Dev

如何在Spring Boot应用程序中配置PageableHandlerMethodArgumentResolver

来自分类常见问题

如何在Spring Boot中设置休息的基本URL?

来自分类Dev

如何在Spring Boot中退出所有缓存?

来自分类常见问题

如何在标准输出中禁用Spring Boot徽标?

来自分类Dev

如何在Spring Boot中动态获取EntityGraph

来自分类Dev

如何在Spring Boot 1.4中自定义Jackson

来自分类Dev

如何在Spring Boot中启用浏览器缓存

Related 相关文章

  1. 1

    如何在Spring Boot SSO + zuul中从OAuth令牌检索范围

  2. 2

    如何在Disqus中查找SSO用户?

  3. 3

    如何在Disqus中查找SSO用户?

  4. 4

    如何在Android应用中实现SSO

  5. 5

    如何在Spring Boot中禁用ErrorPageFilter?

  6. 6

    如何在Spring Boot中添加UrlRewriteFilter

  7. 7

    如何在spring boot中查询关系?

  8. 8

    如何在Spring Boot中覆盖Spring Security默认配置

  9. 9

    如何在Spring Boot中替换Spring ApplicationContext

  10. 10

    SSO Spring kerberos中的注销功能

  11. 11

    spring-boot 1.3-M5 oauth2 SSO不能与spring-session一起使用吗?

  12. 12

    如何在SAML2.0中使用SSO

  13. 13

    如何在Vaadin 14中处理SSO重定向

  14. 14

    如何在 Spring Boot 中使用预定义的令牌绕过 Oauth2 身份验证?

  15. 15

    如何在Spring Boot上验证查询参数的范围

  16. 16

    如何在 Spring Boot 应用程序中从 Api 网关(Zuul)调用外部服务(非 MSA)

  17. 17

    如何在Spring Boot中创建Tcp Connection以接受连接?

  18. 18

    如何在Spring Boot中配置邮件通道?

  19. 19

    如何在Eclipse tomcat中运行Spring Boot App?

  20. 20

    如何在Spring Boot中摆脱JpaRepository接口

  21. 21

    如何在Spring Boot中关闭调试日志消息

  22. 22

    如何在Spring Boot中模拟db连接以进行测试?

  23. 23

    如何在Spring Boot应用程序中配置PageableHandlerMethodArgumentResolver

  24. 24

    如何在Spring Boot中设置休息的基本URL?

  25. 25

    如何在Spring Boot中退出所有缓存?

  26. 26

    如何在标准输出中禁用Spring Boot徽标?

  27. 27

    如何在Spring Boot中动态获取EntityGraph

  28. 28

    如何在Spring Boot 1.4中自定义Jackson

  29. 29

    如何在Spring Boot中启用浏览器缓存

热门标签

归档