java—zuul的替代方法,将存储在httpsession中的自定义令牌作为请求参数转发

w7t8yxp5  于 2021-06-29  发布在  Java
关注(0)|答案(0)|浏览(287)

由于netflixzuul不再处于开发阶段,spring启动支持也处于维护模式,所以我正在寻找一个替代方案。在zuul中,必须能够将会话属性作为请求参数传递给后端服务。我看过springcloudgateway,但是这种被动的风格仍然让我很困惑,我怀疑是否有可能构建与zuul类似的过滤器。但如果有人知道SpringCloudGateway或其他产品的解决方案,我会很高兴。

背景

在我们公司,我们有一个遗留的自制单点登录门户,它将带有httppost的自定义json令牌发送到各个应用程序。大多数都是用jsf构建的老式java应用程序。
应用程序使用一个共享库,其中包含一个servlet过滤器,用于处理这些令牌并将当前用户存储在 HttpSession . 非常简单,它看起来是这样的:

public class AuthFilter implements javax.servlet.Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpSession session = httpRequest.getSession();

        if (httpRequest.getMethod().equals("POST") && httpRequest.getParameter("user") != null) {
            // Just for simplication, no decryption or verification here 
            User user = User.fromJSON(httpRequest.getParameter("user"));
            session.invalidate();
            session = httpRequest.getSession(true);
            session.setAttribute("user", user);
            httpResponse.sendRedirect(httpRequest.getRequestURL().toString());
        }
        else if (session.getAttribute("user") != null) {
            User user = (User) session.getAttribute("user");
            chain.doFilter(request, response);
        }
        else {
            httpResponse.sendError(HttpStatus.SC_UNAUTHORIZED);
        }
    }
}

还有一种身份验证服务,可以方便地访问会话中存储的用户。类似这样的内容(也非常简化):

@Service
@SessionScope
public class AuthService {

    private final HttpSession session;

    @Autowired
    public AuthService(HttpSession session) {
        this.session = session;
    }

    public boolean isLoggedIn() {
        return session.getAttribute("user") != null;
    }

    public User getUser() {
        return (User) session.getAttribute("user");
    }
}

现在,有一个新的应用程序,不是用jsf构建的,而是作为与rest后端通信的spa前端。后端服务受防火墙(和一个api密钥)保护,但对于大多数查询,您必须传递当前用户,因为它们返回特定于用户的数据。
为了在前端使用sso门户启用登录,我集成了 AuthFilter 从共享库和zuul代理进入其中。我创建了一个zuul过滤器,它从 AuthService 并将其作为请求参数传递给后端服务。像这样:

@Component
@SessionScope
public class MyZuulFilter extends com.netflix.zuul.ZuulFilter {

    private final AuthService authService;

    @Autowired
    public MyZuulFilter(AuthService authService) {
        this.authService = authService;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        Map<String, List<String>> params = convertParameterMap(context.getRequest().getParameterMap());
        User user = authService.getUser();
        params.put("user", List.of(user.getName()));
        context.setRequestQueryParams(params);
        return null;
    }

    private Map<String, List<String>> convertParameterMap(Map<String, String[]> origMap) {
        Map<String, List<String>> newMap = new HashMap<>();
        for (Map.Entry<String, String[]> entry : origMap.entrySet()) {
            newMap.put(entry.getKey(), Arrays.asList(entry.getValue()));
        }
        return newMap;
    }

    [...]
}

这非常简单,对于我们的用例来说非常有效,但是依赖一个不再支持的框架似乎是一个相当大的风险。如果有必要,可以选择扩展共享身份验证库,但是我们的sso门户不支持标准协议,如saml2或oauth2,因此我们需要使用httppost处理这些自定义令牌。
我把一个非常简单的例子放在一起,展示了我们的体系结构,包括sso门户、spa前端和rest后端https://github.com/acme42.

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题