禁止ajax访问shiro管理的登录页面
在使用shiro的时候,对于用户权限的管理,相信很多人都已经很熟悉了。
今天,我这里简单的记录一下我自己调试过程中遇到的问题。主要是登录的操作,禁止通过ajax的方式进行访问。
shiro中,登录过程拒绝ajax的访问操作,主要在FormAuthenticationFilter里面实现的。更具体的说,应该是自己重写AccessControlFilter方法中的onAccessDenied方法。
为什么要禁止ajax的登录?安全的考虑!
先看看自己应用中重写的RdFormAuthenticationFilter,它继承于FormAuthenticationFilter,至于FormAuthenticationFilter和AccessControlFilter的关系,自己看shiro的源码吧。
public class RdFormAuthenticationFilter extends FormAuthenticationFilter {
private String passwordParam;
@Autowired
@Qualifier("mqmKefuService")
private IMqmKefuService mksService;
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
if (request.getAttribute(getFailureKeyAttribute()) != null) {
return true;
}
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
if (isLoginSubmission(request, response)) {
return executeLogin(request, response);
} else {
if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))
|| request.getParameter("ajax") != null) {
HttpServletResponse res = WebUtils.toHttp(response);
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
return true;
}
}
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
String username = (String)SecurityUtils.getSubject().getPrincipal();
if(username == null){
return true;
}
MqmKefu user = mksService.selectByUsername(username);
SecurityUtils.getSubject().getSession().setAttribute(Constants.CURRENT_USER, user);
if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))
|| request.getParameter("ajax") != null) {
// 是ajax请求
httpServletRequest.getRequestDispatcher("/login/timeout/success").forward(httpServletRequest, httpServletResponse);
} else {
//httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + this.getSuccessUrl());
String redirectUrl = httpServletRequest.getContextPath() + "/home";
SavedRequest sr = WebUtils.getSavedRequest(request);
//当用户地址的请求不是在地址栏输入,而是在页面上直接点击登录,那么SavedRequest返回值将会是空的。
if(sr != null) {
redirectUrl = sr.getRequestUrl();
}
httpServletResponse.sendRedirect(redirectUrl);
}
return false;
}
public String getPasswordParam() {
return passwordParam;
}
public void setPasswordParam(String passwordParam) {
this.passwordParam = passwordParam;
}
}
AAAA。这里,重点是下面的这个代码片段:
if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))
|| request.getParameter("ajax") != null) {
HttpServletResponse res = WebUtils.toHttp(response);
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
如何测试呢?很简单!
1. 将shiro的配置中,重写LogoutFilter,并将其redirectUrl的值配置为自己想要的内容,而不是原来默认的DEFAULT_REDIRECT_URL(值为/)。例如,将redirectUrl改为登录的url,这里是/usr/login.
2. 将前端页面的退出,一种用ajax的post或者get方式触发,一种用href直接配置url。
2.1 针对退出url (/usr/logout)以ajax的方式触发事件到后台,代码逻辑将会进入上述代码AAAA,且此时HTTP请求头部含有X-Requested-With。前端将收到401的错误,页面不跳转。
2.2 针对退出url以a标签的href方式,直接由浏览器以http调用后台服务的方式,则不会进入AAAA的代码逻辑。
针对上述的LogoutFilter的重写,可以看看配置文件:
<bean id="sysUserFilter" class="com.roomdis.mqr.infra.shiro.SysUserFilter"/>
<bean id="sysLogoutFilter" class="com.roomdis.mqr.infra.shiro.RdLogoutFilter">
<property name="redirectUrl" value="/user/login"/>
</bean> <bean id="jCaptchaValidateFilter" class="com.roomdis.mqr.infra.shiro.JCaptchaValidateFilter">
<property name="jcaptchaEbabled" value="true"/>
<property name="jcaptchaParam" value="jcaptchaCode"/>
<property name="failureKeyAttribute" value="shiroLoginFailure"/>
</bean> <bean id="filterChainManager" class="com.roomdis.mqr.infra.shiro.RdDefaultFilterChainManager">
<property name="loginUrl" value="/user/login" />
<property name="successUrl" value="/home" />
<property name="unauthorizedUrl" value="/unauth" />
<property name="customFilters">
<util:map>
<entry key="authc" value-ref="authcFilter"/>
<entry key="sysUser" value-ref="sysUserFilter"/>
<entry key="jCaptchaValidate" value-ref="jCaptchaValidateFilter"/>
<entry key="logout" value-ref="sysLogoutFilter" />
</util:map>
</property>
<property name="defaultFilterChainDefinitions">
<value>
/ = anon
/*.png = anon
/css/* = anon
/js/** = anon
/image/* = anon
/index.html = anon
/user/login = jCaptchaValidate,authc
/jcaptcha* = anon
/jcaptcha.jsp = anon
/home = sysUser,user
/logout = logout
<!-- /home = authc, perms[/home] perms 表示需要该权限才能访问的页面 -->
</value>
</property>
</bean>
上述配置的红色部分,是重写LogoutFilter的对应bean的信息。
蓝色部分,要特别注意,logout的url,权限部分处理,必须是和自己代码逻辑中的重定向部分一致使用。例如这里的/logout,对应代码逻辑中的地方(红色)如下:
/**
* logout 即常说的登出操作
*
* @param req
* @param rsp
* @param model
* @return
*/
@GET
@Path("/user/logout")
@Produces(MediaType.APPLICATION_JSON)
public void logout(@Context HttpServletRequest req, @Context HttpServletResponse rsp){
Map<String, Object> infoMap = new HashMap<String, Object>();
String basePath = basePath(req);
String usernamep = req.getParameter("username");
infoMap.put("basePath", basePath);
SecurityUtils.getSubject().getSession().removeAttribute(Constants.CURRENT_USER);
try {
rsp.sendRedirect(req.getContextPath() + "/logout");
} catch (IOException e) {
e.printStackTrace();
}
}
前端的代码:
<p class="checkmove">
<span class="fl sp_title">
<#if username??>
<label id="username">${username}</label>
<a class=logout-btn href="${basePath}/user/logout">退出</a> #能够正常运行,即不会触发401的错误的用法
<!--
<button class=button id="leave">退出</button> #这样子用,配合后台的ajax的方式触发,就会出现401的错误
-->
</#if>
<select>
<option value="">上线</option>
<option value="">离开</option>
<option value="">隐身</option>
<option value="">下线</option>
</select>
</span>
</p>
下面上一个图,看看我的项目雏形!

禁止ajax访问shiro管理的登录页面的更多相关文章
- session过期,拦截ajax请求并跳转登录页面
1.方法一 :1.1使用filter 和ajaxsetup 对ajax进行拦截并跳转登录页面 public void doFilter(ServletRequest request, ServletR ...
- 禁止盗链,强制回登录页面web.config配置
<system.web> <compilation debug="true" targetFramework="4.5" /> < ...
- windwsform登录页面
简单登录设计: 读取用户名密码 数据库表 实体类 数据访问类: 隐藏登录页面: 回车快捷键: 传值到main窗口:
- Shiro 整合SpringMVC 并且实现权限管理,登录和注销
Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大 ...
- Shiro 整合SpringMVC 并实现权限管理,登录和注销
Shiro 整合SpringMVC 并且实现权限管理,登录和注销 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring S ...
- ajax Session失效如何跳转到登录页面
在Struts应用中,我们发出的请求都会经过 相应的拦截器进行相关处理,一般都会有一个用户登录拦截(Session失效拦截):一般请求的话,如果Session失效时,我们会跳到登录页面,可是如果我们采 ...
- 11月10日上午ajax基础知识、用ajax做登录页面、用ajax验证用户名是否可用、ajax动态调用数据库
1.ajax的基础知识 ajax是结合了jquery.php等几种技术延伸出来的综合运用的技术,不是新的内容.ajax也是写在<script>标签里面的. 如果使用ajax一定是要有1个处 ...
- 重写ajax方法实现异步请求session过期时跳转登录页面
jQuery(function($){ // 备份jquery的ajax方法 var _ajax=$.ajax; // 重写ajax方法, $.ajax=function(opt){ var _suc ...
- WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据
WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据 WebForm1.aspx 页面 (原生AJAX请求,写法一) <%@ Page Langu ...
随机推荐
- Python 类变量
class Person: country = "大清" def __init__(self, name, gender): self.name = name self.gende ...
- 2016 多校联赛7 Elegant Construction
Being an ACMer requires knowledge in many fields, because problems in this contest may use physics, ...
- Popover 弹出框 设置top,显示有时是向下的,解决方式
参数里面有个popper-options,官网给的值是{boundariesElement: 'body', gpuAcceleration: false },将这个加上问题就解决了.
- Power BI新主页将使内容的导航和发现变得轻而易举!
微软Power BI 将在近日发布Power BI Home登陆页面的公开预览以及Power BI服务中的新全局搜索功能.登录页将成为所有内容的一站式集合,并提供更快捷的方式来分享你的仪表板.原来在左 ...
- lua 取table长度
http://blog.csdn.net/wangmanjie/article/details/52793902 static int unbound_search (Table *t, unsign ...
- foreach遍历数组、数组的转置与方阵的迹
public class Copy1 { public static void main(String[] args) { array1(); //如果不初始化元素,默认为0 int [][] a = ...
- nodejs的express框架
介绍: Express是由路由和中间件构成一个的nodejs的一种web应用框架; 功能: 可以设置中间件来响应 HTTP 请求. 定义了路由表用于执行不同的 HTTP 请求动作. 可以通过向模板传递 ...
- pycharm 4注册码
pycharm 4 注册码 (4.x版均可使用) 用户名:pycharmLicense key: ===== LICENSE BEGIN =====2581-D36230T00000QoX2zbDCV ...
- Wifi设备接入流程
这是硬件平台下文档结构图,详细了解戳这里具体了解这里. 什么意思呢?要想实现控制wifi设备,基本流程是: 咱自己的wifi设备----------自己的服务器(指图中的厂商服务器)-------微信 ...
- lesson9-小象学院cv
www.sohu.com/a/159976204_717210 生成模型:基于联合概率~共生关系判别模型:基于条件概率~因果关系 生成模型之学习数据分布:1)概率密度函数估计 2)数据样本生成 模型目 ...