Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载?
我们知道Ajax不能做页面redirect
和forward
跳转,所以Ajax请求假如没登录,那么这个请求给用户的感觉就是没有任何反应,而用户又不知道用户已经退出或是 Session 超时了。这个时候如何解决?
Shiro 教程,Ajax请求拦截跳转页面方案
在登录拦截器中,如我们自己定义的LoginFilter
中,先行判断下,是否为 Ajax 请求,如果是 Ajax 请求并且没有相关权限,采用Response
输出一段 JSON 数据返回即可。
判断请求是否为Ajax请求
/**
* 是否是Ajax请求
* @param request
* @return
*/
public static boolean isAjax(ServletRequest request){
String header = ((HttpServletRequest) request).getHeader("X-Requested-With");
if("XMLHttpRequest".equalsIgnoreCase(header)){
LoggerUtils.debug(CLAZZ, "当前请求为Ajax请求");
return Boolean.TRUE;
}
LoggerUtils.debug(CLAZZ, "当前请求非Ajax请求");
return Boolean.FALSE;
}
Response 输出JSON数据
/**
* 使用 response 输出JSON
* @param hresponse
* @param resultMap
* @throws IOException
*/
public static void out(ServletResponse response, Map<String, String> resultMap){
PrintWriter out = null;
try {
response.setCharacterEncoding("UTF-8");//设置编码
response.setContentType("application/json");//设置返回类型
out = response.getWriter();
out.println(JSONObject.fromObject(resultMap).toString());//输出
} catch (Exception e) {
LoggerUtils.fmtError(CLAZZ, e, "输出JSON报错。");
}finally{
if(null != out){
out.flush();
out.close();
}
}
}
Shiro Filter 判断Ajax 请求并且处理
package com.sojson.core.shiro.filter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.filter.AccessControlFilter;
import com.sojson.common.model.UUser;
import com.sojson.common.utils.LoggerUtils;
import com.sojson.core.shiro.CustomShiroSessionDAO;
import com.sojson.core.shiro.token.manager.TokenManager;
/**
*
* <p>
* <p>
* 博客地址:http://www.cnblogs.com/123hll/
* <p>
* <p>
*
* 判断登录
*
* <p>
*
* 区分 责任人 日期 说明<br/>
* 创建 Helei 2017年7月2日 <br/>
*
* @author he-lei
* @email
helei212@foxmail.com* @version 1.0,2017年7月2日 <br/>
*
*/
public class LoginFilter extends AccessControlFilter {
final static Class<LoginFilter> CLASS = LoginFilter.class;
// session获取
CustomShiroSessionDAO customShiroSessionDAO;
@Override
protected boolean isAccessAllowed(ServletRequest request,
ServletResponse response, Object mappedValue) throws Exception {
UUser token = TokenManager.getToken();
if (null != token || isLoginRequest(request, response)) {// &&// isEnabled()
return Boolean.TRUE;
}
if (ShiroFilterUtils.isAjax(request)) {// ajax请求
Map<String, String> resultMap = new HashMap<String, String>();
LoggerUtils.debug(getClass(), "当前用户没有登录,并且是Ajax请求!");
resultMap.put("login_status", "300");
resultMap.put("message",
"u5F53u524Du7528u6237u6CA1u6709u767Bu5F55uFF01");// 当前用户没有登录!
ShiroFilterUtils.out(response, resultMap);
}
return Boolean.FALSE;
}
@Override
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response) throws Exception {
// 保存Request和Response 到登录后的链接
saveRequestAndRedirectToLogin(request, response);
return Boolean.FALSE;
}
public void setCustomShiroSessionDAO(
CustomShiroSessionDAO customShiroSessionDAO) {
this.customShiroSessionDAO = customShiroSessionDAO;
}
}
前端Javascript处理Ajax请求返回值
首先提供一个判断方法:
/**
* 判断是否登录,没登录刷新当前页,促使Shiro拦截后跳转登录页
* @param result ajax请求返回的值
* @returns {如果没登录,刷新当前页}
*/
function isLogin(result){
if(result && result.login_status && result.login_status == 300){
window.location.reload(true);//刷新当前页
}
return !0;//返回true
}
然后来一个栗子:
//改变状态
function changeSessionStatus(sessionIds,status,self){
status = !parseInt(status);
//loading
var load = layer.load();
$.post("${basePath}/member/changeSessionStatus.shtml",{status:status,sessionIds:sessionIds},function(result){
layer.close(load);
if(isLogin(result)){//判断是否登录
if(result && result.status == 200){
return self.text(result.sessionStatusText),
self.attr('status',result.sessionStatus),
self.parent().prev().text(result.sessionStatusTextTd);
layer.msg('操作成功'),!1;
}else{
return layer.msg(result.message,function(){}),!1;
}
}
},'json');
}