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

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

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

背景

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

  1. public class AuthFilter implements javax.servlet.Filter {
  2. @Override
  3. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  4. HttpServletRequest httpRequest = (HttpServletRequest) request;
  5. HttpServletResponse httpResponse = (HttpServletResponse) response;
  6. HttpSession session = httpRequest.getSession();
  7. if (httpRequest.getMethod().equals("POST") && httpRequest.getParameter("user") != null) {
  8. // Just for simplication, no decryption or verification here
  9. User user = User.fromJSON(httpRequest.getParameter("user"));
  10. session.invalidate();
  11. session = httpRequest.getSession(true);
  12. session.setAttribute("user", user);
  13. httpResponse.sendRedirect(httpRequest.getRequestURL().toString());
  14. }
  15. else if (session.getAttribute("user") != null) {
  16. User user = (User) session.getAttribute("user");
  17. chain.doFilter(request, response);
  18. }
  19. else {
  20. httpResponse.sendError(HttpStatus.SC_UNAUTHORIZED);
  21. }
  22. }
  23. }

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

  1. @Service
  2. @SessionScope
  3. public class AuthService {
  4. private final HttpSession session;
  5. @Autowired
  6. public AuthService(HttpSession session) {
  7. this.session = session;
  8. }
  9. public boolean isLoggedIn() {
  10. return session.getAttribute("user") != null;
  11. }
  12. public User getUser() {
  13. return (User) session.getAttribute("user");
  14. }
  15. }

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

  1. @Component
  2. @SessionScope
  3. public class MyZuulFilter extends com.netflix.zuul.ZuulFilter {
  4. private final AuthService authService;
  5. @Autowired
  6. public MyZuulFilter(AuthService authService) {
  7. this.authService = authService;
  8. }
  9. @Override
  10. public Object run() throws ZuulException {
  11. RequestContext context = RequestContext.getCurrentContext();
  12. Map<String, List<String>> params = convertParameterMap(context.getRequest().getParameterMap());
  13. User user = authService.getUser();
  14. params.put("user", List.of(user.getName()));
  15. context.setRequestQueryParams(params);
  16. return null;
  17. }
  18. private Map<String, List<String>> convertParameterMap(Map<String, String[]> origMap) {
  19. Map<String, List<String>> newMap = new HashMap<>();
  20. for (Map.Entry<String, String[]> entry : origMap.entrySet()) {
  21. newMap.put(entry.getKey(), Arrays.asList(entry.getValue()));
  22. }
  23. return newMap;
  24. }
  25. [...]
  26. }

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

暂无答案!

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

相关问题