在使用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. ORACLE中使用DBMS_RANDOM去产生随机数

    一.生成随机字符串:DBMS_RANDOM.STRING 用法:DBMS_RANDOM.STRING(选项, 返回字符串长度) 选项有如下几种可供选择:1)'u', 'U' - returning s ...

  2. 二进制数值Byte [] 转Base64字符串

    将二进制数据转换成Base64字符串: String base64String = new String(byteArray).replaceAll("\n","&quo ...

  3. jQuery的效果(动画)

    jquery的效果(动画) show 概念:显示隐藏的匹配元素 语法:show(speed,callback) 参数:speed:三种预定速度之一的字符串('slow','normal','fast' ...

  4. 了解Git的工作区和暂存区

    Git有工作区,暂存区之分. 1.工作区 我们电脑上的某个被Git管理的文件夹,就是一个工作区. 比如说我的GitWorkText文件夹,如图: 2.版本库(Repository) 在工作区有一个隐藏 ...

  5. Python用re正则化模块在字符串查找特定字符串

    实验需要,在一个含有几亿个字符的txt文件中查找特定的字符串,首先用re模块进行查找 from time import clock import re start=clock() label_file ...

  6. Windows 下使用nginx命令启动

    http://wanganwu.blog.163.com/blog/static/7788722012322111417966/ Windows下Nginx的启动.停止等命令 在Windows下使用N ...

  7. POJ 2456: Aggressive cows(二分,贪心)

    Aggressive cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20485   Accepted: 9719 ...

  8. HPU第四次积分赛-L:A Winged Steed(完全背包)

    A Winged Steed 描述 有n种千里马,每一种都有若干匹,第i种马的颜值ai​,价格di​.现有m个牧马人要去挑选千里马,每一位牧马人对马的颜值都有要求:{所选马的颜值总和} ⩾Ai​.现在 ...

  9. python django day 4 database

    django-admin.py startproject learn_models # 新建一个项目 cd learn_models # 进入到该项目的文件夹 django-admin.py star ...

  10. 简单的Windows应用程序命名规则

    读书:<高质量C++编程指南> 作者对“匈牙利”命名规则做了合理的简化,下述的命名规则简单易用,比较适合于Windows应用软件的开发. l [规则3-2-1]类名和函数名用大写字母开头的 ...