如何将已通过身份验证的用户从登录页面重定向到主页
Posted
技术标签:
【中文标题】如何将已通过身份验证的用户从登录页面重定向到主页【英文标题】:How to redirect already authenticated user from login page to home page 【发布时间】:2013-12-15 11:46:44 【问题描述】:我正在使用 Apache Shiro 开发 JSF 应用程序。我用 Shiro 对用户进行身份验证并将她重定向到主页,这没有问题。在我尝试访问登录页面时进行身份验证后,它不会重定向我的主页。即使已经有登录用户,我也可以再次登录。正如 BalusC 在他的博客文章中提到的那样,我正在做 Programmatic Login。
[main]
credentialsMatcher = org.apache.shiro.authc.credential.PasswordMatcher
myRealm = com.example.security.myRealm
myRealm.credentialsMatcher = $credentialsMatcher
securityManager.realms = $myRealm
user = com.example.web.filter.FacesAjaxAwareUserFilter
user.loginUrl = /login.xhtml
[urls]
/login.xhtml = user
此过滤器是从博客文章中编写的。
public class FacesAjaxAwareUserFilter extends UserFilter
private static final String FACES_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<partial-response><redirect url=\"%s\"></redirect></partial-response>";
@Override
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException
HttpServletRequest req = (HttpServletRequest) request;
if ("partial/ajax".equals(req.getHeader("Faces-Request")))
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.getWriter().printf(FACES_REDIRECT_XML, req.getContextPath() + getLoginUrl());
else
super.redirectToLogin(request, response);
问题是什么?如果用户已经通过身份验证,我该如何重定向?
编辑: 现在,如果用户已经通过身份验证,我正在使用 PostConstruct 注释进行重定向。我愿意接受任何好的解决方案。
【问题讨论】:
【参考方案1】:当我尝试访问登录页面时,经过身份验证后,它不会重定向我的主页。即使已经有登录用户,我也可以再次登录
Shiro 和自定义 Shiro 用户过滤器都不是为了防止这种情况发生。 Shiro 没有内置的设施。自定义 Shiro 用户过滤器仅在找到未经身份验证的用户时运行,而不是在找到已通过身份验证的用户时运行。
防止经过身份验证的用户直接访问登录页面是您自己的责任。根据业务需求,您可以执行以下操作:
请允许。也许用户只是想切换登录。如有必要,您可以有条件地显示如下消息:
<ui:fragment rendered="#not empty request.remoteUser">
You are already logged-in as #request.remoteUser.
By logging in as another user, you will be logged out.
</ui:fragment>
<h:form id="login">
...
</h:form>
不允许,但要保持在同一页面上。有条件地隐藏登录表单并显示如下消息:
<ui:fragment rendered="#not empty request.remoteUser">
Hey, how did you end up here?
You are already logged-in as #request.remoteUser!
</ui:fragment>
<h:form id="login" rendered="#empty request.remoteUser">
...
</h:form>
当然,当用户已经登录时,请确保您的 Web 应用程序在任何地方都没有登录链接。
不允许它并重定向到所需的目标页面。这又可以通过多种方式完成。最干净的方法是使用 servlet 过滤器。
@WebFilter(urlPatterns = "/login.xhtml")
public class LoginPageFilter implements Filter
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (request.getRemoteUser() != null)
response.sendRedirect(request.getContextPath() + "/home.xhtml"); // Redirect to home page.
else
chain.doFilter(req, res); // User is not logged-in, so just continue request.
// Add/generate init() and destroy() with NOOP.
You can also do this in a preRenderView
event listener。 @PostConstruct
可能为时已晚,因为此时响应可能已经提交。请注意,没有任何形式的反馈的重定向可能会让最终用户感到困惑。在过滤器中,考虑传递一个应该触发条件消息的附加参数。或者在preRenderView
事件监听器中,设置一个flash 作用域的消息。
【讨论】:
以上是关于如何将已通过身份验证的用户从登录页面重定向到主页的主要内容,如果未能解决你的问题,请参考以下文章
Flask - 如果当前用户未通过身份验证,如何重定向到登录页面?