在使用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管理的登录页面的更多相关文章

  1. session过期,拦截ajax请求并跳转登录页面

    1.方法一 :1.1使用filter 和ajaxsetup 对ajax进行拦截并跳转登录页面 public void doFilter(ServletRequest request, ServletR ...

  2. 禁止盗链,强制回登录页面web.config配置

    <system.web> <compilation debug="true" targetFramework="4.5" /> < ...

  3. windwsform登录页面

    简单登录设计: 读取用户名密码 数据库表 实体类 数据访问类: 隐藏登录页面: 回车快捷键: 传值到main窗口:

  4. Shiro 整合SpringMVC 并且实现权限管理,登录和注销

    Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大 ...

  5. Shiro 整合SpringMVC 并实现权限管理,登录和注销

    Shiro 整合SpringMVC 并且实现权限管理,登录和注销 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring S ...

  6. ajax Session失效如何跳转到登录页面

    在Struts应用中,我们发出的请求都会经过 相应的拦截器进行相关处理,一般都会有一个用户登录拦截(Session失效拦截):一般请求的话,如果Session失效时,我们会跳到登录页面,可是如果我们采 ...

  7. 11月10日上午ajax基础知识、用ajax做登录页面、用ajax验证用户名是否可用、ajax动态调用数据库

    1.ajax的基础知识 ajax是结合了jquery.php等几种技术延伸出来的综合运用的技术,不是新的内容.ajax也是写在<script>标签里面的. 如果使用ajax一定是要有1个处 ...

  8. 重写ajax方法实现异步请求session过期时跳转登录页面

    jQuery(function($){ // 备份jquery的ajax方法 var _ajax=$.ajax; // 重写ajax方法, $.ajax=function(opt){ var _suc ...

  9. WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据

    WebForm.aspx 页面通过 AJAX 访问WebForm.aspx.cs类中的方法,获取数据 WebForm1.aspx 页面 (原生AJAX请求,写法一) <%@ Page Langu ...

随机推荐

  1. python day04 作业答案

    1. 1) li=['alex','WuSir','ritian','barry','wenzhou'] print(len(li)) 2) li=['alex','WuSir','ritian',' ...

  2. Python MRO_C3

    class A: pass class B(A): pass class C(A): pass class D(B, C): pass class E(C, A): pass class F(D, E ...

  3. [转]谈谈 Bias-Variance Tradeoff

    https://liam0205.me/2017/03/25/bias-variance-tradeoff/ 谢谢原作者! 谈谈 Bias-Variance Tradeoff 发表于 2017 年 0 ...

  4. INS-20802 Oracle Cluster Verification Utility failed解释说明

    背景:安装RAC,安装GI集群管理软件时,在最后快结束时,总是报如上INS-错误 #官方文档:error 说明;字符串解析失败 INS-20802: string failed. Cause: The ...

  5. [LeetCode&Python] Problem 905: Sort Array By Parity

    Given an array A of non-negative integers, return an array consisting of all the even elements of A, ...

  6. ortp 发送RTP实例

    参考源代码目录src/tests/rtpsend.c     ortp_init();     ortp_scheduler_init();     ortp_set_log_level_mask(O ...

  7. java-类与类,类与接口,接口与接口的关系

    1.类与类: - 继承关系,只能单继承,可以多层继承. 2.类与接口: - 实现关系,可以单实现,也可以多实现. - 并且还可以在继承一个类的同时实现多个接口. - * 例:class Demo ex ...

  8. (21)jq动画

    jq动画的优点 优点: 1.可以知道动画结束的表示(结束的回调函数) 2.可以利用jq动画插件完成复杂的动画 动画有三个参数:动画的样式是字典.动画持续的事件,动画结束回调函数 <!DOCTYP ...

  9. djkstra nlogn

    #include<bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> usi ...

  10. python基础(八)——多线程

    [root@bogon python]# cat test.py #!/usr/bin/ptyhon import thread import time def print_time(threadNa ...