用了shiro一段时间了,但是有点受不了它请求登录如果验证不通过直接跳的是loginUrl…所以我想很多人想用ajax实现shiro的登录直接在回调函数里面通过js显示出错信息吧。

今天查了一天的资料,结合了别人写的文章,自己也写了这个博客。好了,直接进入主题吧~

首先我们知道shiro主要是通过过滤器来实现权限的验证的,你可以继承各种各样的filter来进行扩展。这里我们实现ajax是通过继承FormAuthenticationFilter来的。下面这个类实现了如果是ajax请求则直接处理登录之后直接将信息通过response返回给客户端,如果是其它请求则直接用的源代码执行下去的,只是把源代码copy到重写的方法里面的而已。具体的可以看源码就会清楚的哦~如下:

package com.sh.ddyc.shiro.filter;

import com.sh.ddyc.constant.Constant;
import com.sh.ddyc.data.mapper.DUserMapper;
import com.sh.ddyc.dto.UserDto;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

public class ExtendFormAuthenticationFilter extends FormAuthenticationFilter {

private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);

@Autowired
DUserMapper userMapper;

/**
* 表示当访问拒绝时
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

if(this.isLoginRequest(request, response)) {
if(this.isLoginSubmission(request, response)) {
if(log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}

return this.executeLogin(request, response);
} else {
if(log.isTraceEnabled()) {
log.trace("Login page view.");
}

return true;
}
} else {
if(log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the Authentication url [" + this.getLoginUrl() + "]");
}

this.saveRequestAndRedirectToLogin(request, response);
return false;
}
}

/**
* 当登录成功
* @param token
* @param subject
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
//将user对象放入session,这里你可能用不到,可以删除
Map<String,String> params = new HashMap<String,String>();
params.put("username",token.getPrincipal().toString());
UserDto userDto = userMapper.findUserDto(params);
//----------以上代码你可以删除-------------------
((HttpServletRequest)request).getSession().setAttribute(Constant.CURRENT_USER,userDto);

HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;

if (!"XMLHttpRequest".equalsIgnoreCase(httpServletRequest
.getHeader("X-Requested-With"))) {// 不是ajax请求
issueSuccessRedirect(request, response);
} else {
httpServletResponse.setCharacterEncoding("UTF-8");
PrintWriter out = httpServletResponse.getWriter();
out.println("{\"success\":true,\"message\":\"登入成功\"}");
out.flush();
out.close();
}
return false;
}

/**
* 当登录失败
* @param token
* @param e
* @param request
* @param response
* @return
*/
@Override
protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
if (!"XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest) request)
.getHeader("X-Requested-With"))) {// 不是ajax请求
setFailureAttribute(request, e);
return true;
}
try {
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String message = e.getClass().getSimpleName();
if ("IncorrectCredentialsException".equals(message)) {
out.println("{\"success\":false,\"message\":\"密码错误\"}");
} else if ("UnknownAccountException".equals(message)) {
out.println("{\"success\":false,\"message\":\"账号不存在\"}");
} else if ("LockedAccountException".equals(message)) {
out.println("{\"success\":false,\"message\":\"账号被锁定\"}");
} else {
out.println("{\"success\":false,\"message\":\"未知错误\"}");
}
out.flush();
out.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return false;
}
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134

上面这个类的onAccessDenied()方法表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。onLoginSuccess()方法是登录成功时调用。onLoginFailure()方法是登录失败时调用。
下面是onAccessDenied()方法里面的this.executeLogin(request, response);这行代码的源码:

可以看出这个方法执行了subject的login()方法登录然后如果登录成功则调用的onLoginSuccess(),如果报错则调用的onLoginFailure()。

好啦,关键的部分讲完了,接下来就是xml的配置了。
喽~

<!-- 继承FormAuthenticationFilter基于Form表单的身份验证过滤器,用于扩展 -->
<bean id="formAuthenticationFilter" class="com.sh.ddyc.shiro.filter.ExtendFormAuthenticationFilter">
<property name="usernameParam" value="username"/>
<property name="passwordParam" value="password"/>
<property name="rememberMeParam" value="rememberMe"/>
<property name="loginUrl" value="/login"/>
</bean>
<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
<property name="successUrl" value="/index" />
<property name="filters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter"/>
<entry key="kickout" value-ref="kickoutSessionControlFilter"/>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/login = authc
/index.jsp = anon
/*/register* = anon
/logout = logout
/static/** = anon
/assets/** = anon
/image/** = anon
/images/** = anon
/** = kickout,authc
</value>
</property>
</bean>1234567891011121314151617181920212223242526272829303132

接下来,你就可以直接在客户端用js请求login了~

这里的客户端js用ajax请求就自己写好了~
0.0

shiro用ajax方式登录的更多相关文章

  1. [实战]MVC5+EF6+MySql企业网盘实战(6)——ajax方式登录

    写在前面 今天回来的比较早,就趁着有空,把登录的代码更新一下.上篇文章实现了ajax的注册,这篇将实现登录,实现目标,ajax登录方式,如果勾选记住我,则下次不再输入用户名密码,直接跳转到网盘界面. ...

  2. 项目一:第十一天 2、运单waybill快速录入 3、权限demo演示-了解 5、权限模块数据模型 6、基于shiro实现用户认证-登录(重点)

    1. easyui DataGrid行编辑功能 2. 运单waybill快速录入 3. 权限demo演示-了解 4. Apache shiro安全框架概述 5. 权限模块数据模型 6. 基于shiro ...

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

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

  4. Shiro启用注解方式

    shiro验证权限方式一种是基于url配置文件: 例如: <bean id="shiroFilter" class="org.apache.shiro.spring ...

  5. ajax基础语法、ajax做登录、ajax做用户名验证是否可用、ajax做关键字查询动态显示、ajax做用表格显示数据并增加操作列

    AJAX: AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新.   ...

  6. ajax 做登录 实现页面免刷新

    结合之前学的知识,可以用ajax来传递数据,实现页面不用刷新,仅数据刷新,来看一下ajax是怎么来实现页面免刷新的 方的是客户端,圆的是服务器 如果没有ajax的话,客户端直接把数据传给服务器,服务器 ...

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

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

  8. 14.ajax基础知识、用ajax做登录页面、用ajax验证用户名是否可用、ajax动态调用数据库

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

  9. 使用 jQuery Ajax 异步登录,并验证用户输入信息(maven)

    使用 jQuery Ajax 异步登录,并验证用户输入信息(maven) 本篇内容: (1)上一篇是使用同步的请求实现登录,并由 Servlet 决定登陆后下一步做哪些事情,本篇使用 jQuery A ...

随机推荐

  1. Codeforces Round #620 (Div. 2) C. Air Conditioner

    Gildong owns a bulgogi restaurant. The restaurant has a lot of customers, so many of them like to ma ...

  2. CDH

    CDH 1.CDH简介 CDH 2.Cloudera Manager的安装     软件下载地址: 链接:https://pan.baidu.com/s/1C5HpiVEOtH_4PjylyJaXvA ...

  3. 大盘及策略收益率的公式推导与Python代码

    一.模型前提与假设 设策略总天数为\(n\).第\(t\)日大盘的收盘价为\(P_t\).第\(t\)日的单日收益率为\(r_t\).\(n\)天的累积收益率为\(r_{cum}\) 假设策略仅买卖大 ...

  4. 九、web.xml理解

    1.web.xml文件在每个web工程不是必须要有的:     web.xml文件是用来初始化配置信息:比如Welcome页面.servlet.servlet-mapping.filter.liste ...

  5. python闯关之路一(语法基础)

      1,什么是编程?为什么要编程? 答:编程是个动词,编程就等于写代码,那么写代码是为了什么呢?也就是为什么要编程呢,肯定是为了让计算机帮我们搞事情,代码就是计算机能理解的语言. 2,编程语言进化史是 ...

  6. OBS输出设置

    参数建议来自虎牙 https://help.huya.com/284 3.输出: 1)编码器中x264相当于虎牙直播中的CPU H.264编码,NVENC H.264相当于虎牙直播中的NVIDIA H ...

  7. ajax方法详解

    $.ajax()常用参数的设置及其意义 $.ajax({ async:true, /*是否异步请求,用这对象的目的就是为了异步请求,所以此值一般不变,恒为true*/ cache:false, /*是 ...

  8. Django 学习之Django Rest Framework(DRF)

    一. WEB应用模式 在开发Web应用中,有两种应用模式 1. 前后端不分离 把html模板文件和django的模板语法结合渲染完成以后才从服务器返回给客户. 2. 前后端分离 二. API接口 AP ...

  9. iOS中统计平台的使用

    iOS腾讯Bugly使用  https://www.jianshu.com/p/f672e0d202ef iOS 百度统计的使用技巧 https://blog.csdn.net/yy1992320/a ...

  10. Ubuntu开启端口(持久化)

    1.查看已经开启的端口 sudo ufw status 2.打开80端口 sudo ufw allow 3.防火墙开启 sudo ufw enable 4.防火墙重启 sudo ufw reload