关于一个浏览器同时登陆多个账户,自动跳转到原登录页面的逻辑错误。
方法1
对shiro源码进行了调试,发现是AuthenticationFilter验证逻辑的问题:
1.它首先验证是否有允许访问页面(isAccessAllowed方法)。
2.在拒绝访问中(FormAuthenticationFilter的onAccessDenied方法)才会进行判断是否是登录提交(isLoginSubmission)。
因为已经登陆了一个用户所以isAccessAllowed直接返回为true,进入LoginController,找到匹配方法fail直接返回LOGIN_PAGE。
由于有权限访问该登录(其他)页面FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME没有值,返回为Null,所以在
keta-security中会跳转到login页面并且显示"登陆失败,其他错误!"。
分析、修改逻辑,首先验证是否是登录操作,再进行验证是否有权限访问页面。继承FormAuthenticationFilter,覆盖isAccessAllowed方法。
03 | * @author <a href="mailto:ketayao@gmail.com">ketayao</a> |
05 | * @since 2012-10-29 上午9:37:02 |
08 | public class BaseFormAuthenticationFilter extends FormAuthenticationFilter { |
09 | private static final Logger log = LoggerFactory.getLogger(BaseFormAuthenticationFilter. class ); |
17 | * @see org.apache.shiro.web.filter.authc.AuthenticatingFilter#isAccessAllowed(javax.servlet.ServletRequest, javax.servlet.ServletResponse, java.lang.Object) |
20 | protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { |
23 | if (isLoginSubmission(request, response)) { |
24 | if (log.isTraceEnabled()) { |
25 | log.trace( "Login submission detected. Attempting to execute login." ); |
29 | } catch (Exception e) { |
30 | log.error(Exceptions.getStackTraceAsString(e)); |
33 | return super .isAccessAllowed(request, response, mappedValue); |
方法2
- 在loginUrl页面判断用户是否已经登陆,如果已经登陆了,则提示用户可以选择进入系统或者登出:
<ui:fragment rendered="#{not empty request.remoteUser}">
您已经登陆系统,请选择<a href="dashboard.html">进入系统</>,或者<a href="logout.do">登出系统来用其它用户登陆</>
</ui:fragment>
- 方法3
- 或者,你希望用户这样干的时候,直接将其重定向到系统首页去,则利用filter来做此事
@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");
} else {
chain.doFilter(req, res);
}
}
}