方法一:重写FormAuthenticationFilter
原理:
假设在shiro.xml中配置了 /** = authc
而默认authc对应org.apache.shiro.web.filter.authc.FormAuthenticationFilter过滤器
则表示所有路径都被此过滤器拦截
当未登录请求被拦截,会调用FormAuthenticationFilter.onAccessDeny():
如果请求的是loginUrl,则调用AuthenticatingFilter.executeLogin()
如果不是,则使request重定向到loginUrl,并return false;
AuthenticatingFilter.executeLogin():
调用subject.login(token)
如果登录成功,则调用onLoginSuccess()
失败则调用onLoginFailure()
AuthenticatingFilter.onLoginSuccess(): return true;
AuthenticatingFilter.onLoginFailure(): return false;
subject.login(token):
最终会调用realm的doGetAuthenticationInfo
思路
重写默认的FormAuthenticationFilter,
在onAccessDeny()方法中:
如果请求的是loginUrl,则调用AuthenticatingFilter.executeLogin()
如果不是,则返回json,提示“未登录,无法访问该地址”
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (this.isLoginRequest(request, response)) {
if (this.isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return this.executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
return true;
}
} else {
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the Authentication url [" + this.getLoginUrl() + "]