php ajax session死锁,shiro处理ajax请求session失效跳转

最近在学习shiro时遇到一个问题,在ajax请求时,如果session失效时,无法正确的跳转登录页面。在之前的项目中处理的方法是通过自定义一个过滤器来处理,session失效时返回错误码来处理。但因为使用shiro后,会先执行shiro定义的过滤器,才会执行自定义的过滤器,所以之前的方法行不通,参考了很多大大的博客,把我的处理方法贴上。

1.自定义拦截器LoginFormFilter拦截器,继承FormAuthenticationFilter类,在需要登录而未登录的请求都会执行onAccessDenied请求。

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请求的话,也无法跳转。

2.shiro的配置类中配置拦截器。(此处使用了spring boot)

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过滤器。

3.前台js中全局捕获这个aja求返回的错误码。

$.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即可。

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.效果图:

a4c17667a057e8c65d81b91c30936702.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值