shiro处理ajax请求未登录,shiro处理ajax请求session失效跳转
最近在学习shiro时遇到一个问题,在ajax请求时,若是session失效时,没法正确的跳转登陆页面。在以前的项目中处理的方法是经过自定义一个过滤器来处理,session失效时返回错误码来处理。但由于使用shiro后,会先执行shiro定义的过滤器,才会执行自定义的过滤器,因此以前的方法行不通,参考了不少大大的博客,把个人处理方法贴上。javascript
1.自定义拦截器LoginFormFilter拦截器,继承FormAuthenticationFilter类,在须要登陆而未登陆的请求都会执行onAccessDenied请求。css
package com.xxfy.demo.filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xxfy.demo.util.HttpUtils;
public class LoginFormFilter extends FormAuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(LoginFormFilter.class);
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
//allow them to see the login page ;)
return true;
}
} else {
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the " +
"Authentication url [" + getLoginUrl() + "]");
}
//若是是Ajax请求,不跳转登陆
if (HttpUtils.isAjax(httpServletRequest)){
System.out.println("ajax");
httpServletResponse.setStatus(401);
} else {
saveRequestAndRedirectToLogin(request, response);
}
return false;
}
}
}
此处的onAccessDenied方法跟FormAuthenticationFilter基本相似,只是加了一段判断是ajax请求的代码 ,若是是ajax请求的话,直接返回错误码,而不是跳转登陆,由于若是是ajax请求的话,也没法跳转。java
2.shiro的配置类中配置拦截器。(此处使用了spring boot)jquery
package com.xxfy.demo.config;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.xxfy.demo.filter.LoginFormFilter;
/**
* shiro配置类
* @author Administrator
*
*/
@Configuration
public class ShiroConfiguration {
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map filterChainDefinitionMap = new LinkedHashMap();
//配置退出过滤器,其中的具体的退出代码Shiro已经替咱们实现了
filterChainDefinitionMap.put("/logout", "logout");
//静态资源能够不登陆访问
/* filterChainDefinitionMap.put("/static/**", "anon");*/
filterChainDefinitionMap.put("/assets/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/unauth", "anon");
//filterChainDefinitionMap.put("/admin/index", "roles['admin']");
//全部请求都须要登陆才能够访问
filterChainDefinitionMap.put("/**", "authc");
//登陆请求
shiroFilterFactoryBean.setLoginUrl("/login");
//登陆成功跳转的页面
shiroFilterFactoryBean.setSuccessUrl("/admin/index");
Map filters = new HashMap();
Filter loginFilter = new LoginFormFilter();
filters.put("authc", loginFilter); //此处使用自定义的拦截器,autho默认使用FormAuthenticationFilter拦截器
shiroFilterFactoryBean.setFilters(filters);
//没有权限的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public AuthorizingRealm myShiroRealm() {
AuthorizingRealm myRealm = new MyShiroRealm();
myRealm.setCredentialsMatcher(customCredentialsMatcher());
return myRealm;
}
@Bean
public CustomCredentialsMatcher customCredentialsMatcher() {
CustomCredentialsMatcher customCredentialsMatcher = new CustomCredentialsMatcher();
customCredentialsMatcher.setHashAlgorithmName("MD5");
return customCredentialsMatcher;
}
}
此处的关键就是代码就是这个:filters.put("authc", loginFilter);这里使用第一步的过滤器,shiro默认使用FormAuthenticationFilter过滤器。web
3.前台js中全局捕获这个aja求返回的错误码。ajax
$.ajaxSetup({
type: "POST",
complete: function(jqXHR, textStatus){
switch (jqXHR.status){
case(500):
alert("服务器系统内部错误");
break;
case(401):
$("#loginModal").modal("show");
break;
case(403):
alert("无权限执行此操做");
break;
case(408):
alert("请求超时");
break;
default:
alert("未知错误");
}
},
success: function(data){
alert("操做成功");
}
});
4.增长一步无关的一步,做为本身的记录,项目使用了jquery.datatable做为数据展现,使用这种方法处理ajax请求时,若是session失效,进行查询返回的确定就不会是json格式的数据,datatable会有一个自身的提示信息,须要把它去掉,此时只要在请求中增长error便可。spring
var table = $('#example').DataTable({
//开启服务器模式
serverSide: true,
//禁用搜索
searching: false,
//禁用排序
ordering: false,
//数据来源(包括处理分页,排序,过滤) ,即url,action,接口,等等
ajax: {
url : $("#contextPath").val() + "/admin/permissions/user/list",
type:"post",
data : function(d){
d.userId=$("#userId").val();
d.userName=$("#userName").val();
d.sex=$("#sex").val();
d.tel=$("#tel").val();
},
error:function(data) {
}
},
5.效果图:apache

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)