由于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.
暂无答案!
目前还没有任何答案,快来回答吧!