Spring 引导和 Spring 安全中的入职过滤器
Onboarding filter in Spring Boot and Spring Security
我正在尝试创建一个过滤器,以便将登录的用户重定向到入职页面,以防他们之前没有完成该过程。
到目前为止,这是我的过滤器:
@Component
@Order(110)
public class OnboardingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// cast the request and response to HTTP
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
SecurityContextImpl securityContext = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");
// if there's a logged user
if (securityContext != null) {
UserPrincipal principal = (UserPrincipal) securityContext.getAuthentication().getPrincipal();
if (!principal.hasOnboarded()) {
httpResponse.sendRedirect("/onboarding");
}
}
// continue with the filter chain
chain.doFilter(httpRequest, httpResponse);
}
我已经为 @Order
尝试了不同的值,但在每种情况下,http 响应都会生成可下载的内容,而不是显示实际请求的 URL 或发送重定向。有什么想法吗?
我遇到了这个异常:
Caused by: java.lang.IllegalStateException: Committed
at org.eclipse.jetty.server.HttpChannel.resetBuffer(HttpChannel.java:917)
HttpChannel.java:917
at org.eclipse.jetty.server.HttpOutput.resetBuffer(HttpOutput.java:1423)
HttpOutput.java:1423
at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1182)
Response.java:1182
at org.eclipse.jetty.server.Response.sendRedirect(Response.java:534)
Response.java:534
at org.eclipse.jetty.server.Response.sendRedirect(Response.java:543)
Response.java:543
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.firewall.FirewalledResponse.sendRedirect(FirewalledResponse.java:43)
FirewalledResponse.java:43
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.web.servlet.view.RedirectView.sendRedirect(RedirectView.java:627)
RedirectView.java:627
at org.springframework.web.servlet.view.RedirectView.renderMergedOutputModel(RedirectView.java:314)
RedirectView.java:314
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
AbstractView.java:316
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
DispatcherServlet.java:1373
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
DispatcherServlet.java:1118
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
DispatcherServlet.java:1057
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
DispatcherServlet.java:943
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
FrameworkServlet.java:1006
... 94 common frames omitted
在
中添加一个return
怎么样?
httpResponse.sendRedirect("/onboarding");
return;
否则您将继续过滤器链:
chain.doFilter(httpRequest, httpResponse);
不能 100% 确定这是否已经解决了您的问题,但可能也是一个问题。
我最终通过实现 Spring 上下文感知 GenericFilterBean
解决了这个问题,如下所示:
public class OnboardingFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (SecurityContextHolder.getContext().getAuthentication() != null) {
// some business logic
httpResponse.sendRedirect("/onboarding");
}
else {
chain.doFilter(httpRequest, httpResponse);
}
}
}
别忘了将其添加到安全过滤器链中:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new OnboardingFilter(), UsernamePasswordAuthenticationFilter.class)...
我正在尝试创建一个过滤器,以便将登录的用户重定向到入职页面,以防他们之前没有完成该过程。
到目前为止,这是我的过滤器:
@Component
@Order(110)
public class OnboardingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// cast the request and response to HTTP
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
SecurityContextImpl securityContext = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");
// if there's a logged user
if (securityContext != null) {
UserPrincipal principal = (UserPrincipal) securityContext.getAuthentication().getPrincipal();
if (!principal.hasOnboarded()) {
httpResponse.sendRedirect("/onboarding");
}
}
// continue with the filter chain
chain.doFilter(httpRequest, httpResponse);
}
我已经为 @Order
尝试了不同的值,但在每种情况下,http 响应都会生成可下载的内容,而不是显示实际请求的 URL 或发送重定向。有什么想法吗?
我遇到了这个异常:
Caused by: java.lang.IllegalStateException: Committed
at org.eclipse.jetty.server.HttpChannel.resetBuffer(HttpChannel.java:917)
HttpChannel.java:917
at org.eclipse.jetty.server.HttpOutput.resetBuffer(HttpOutput.java:1423)
HttpOutput.java:1423
at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1182)
Response.java:1182
at org.eclipse.jetty.server.Response.sendRedirect(Response.java:534)
Response.java:534
at org.eclipse.jetty.server.Response.sendRedirect(Response.java:543)
Response.java:543
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.firewall.FirewalledResponse.sendRedirect(FirewalledResponse.java:43)
FirewalledResponse.java:43
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
at org.springframework.web.servlet.view.RedirectView.sendRedirect(RedirectView.java:627)
RedirectView.java:627
at org.springframework.web.servlet.view.RedirectView.renderMergedOutputModel(RedirectView.java:314)
RedirectView.java:314
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
AbstractView.java:316
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
DispatcherServlet.java:1373
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
DispatcherServlet.java:1118
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
DispatcherServlet.java:1057
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
DispatcherServlet.java:943
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
FrameworkServlet.java:1006
... 94 common frames omitted
在
中添加一个return
怎么样?
httpResponse.sendRedirect("/onboarding");
return;
否则您将继续过滤器链:
chain.doFilter(httpRequest, httpResponse);
不能 100% 确定这是否已经解决了您的问题,但可能也是一个问题。
我最终通过实现 Spring 上下文感知 GenericFilterBean
解决了这个问题,如下所示:
public class OnboardingFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (SecurityContextHolder.getContext().getAuthentication() != null) {
// some business logic
httpResponse.sendRedirect("/onboarding");
}
else {
chain.doFilter(httpRequest, httpResponse);
}
}
}
别忘了将其添加到安全过滤器链中:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new OnboardingFilter(), UsernamePasswordAuthenticationFilter.class)...