用了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. 5_7 丑数(UVa136)<priority_queue的使用>

    Ugly Number的定义为:该数之质因数必须为2,3或5,当然了,依照惯例,1也算是Ugly Number.在此列举一串数列:1,2,3,4,5,6,8,9,10,12,15这些就是前11个Ugl ...

  2. C:char类型

    char字符类型 字符型变量用于存储一个单一字符,在 C 语言中用 char 表示,其中每个字符变量都会占用 1 个字节.在给字符型变量赋值时,需要用一对英文半角格式的单引号(' ')把字符括起来. ...

  3. Bugku-CTF加密篇之ok(Ook!)

  4. Django安装数据库MySQLdb

    在使用Django搭建与树莓派智能终端时,使用mysql作为数据库管理,遇到如下问题: django.core.exceptions.ImproperlyConfigured: Error loadi ...

  5. 吴裕雄--天生自然TensorFlow2教程:函数优化实战

    import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D def himme ...

  6. 洛谷P1086花生采摘(简单模拟)

    题目描述 鲁宾逊先生有一只宠物猴,名叫多多.这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”. 鲁宾逊先生和多多都很开心,因为花生正是他 ...

  7. mxgraph初体验

    最近公司让学习了mxgraph,简单总结一下 (1)mxGraph学习路径 1)API:http://jgraph.github.io/mxgraph/docs/js-api/files/index- ...

  8. 【原】mac电脑使用总结

    mac下终端配置(item2+oh-my-zsh)+solarized配色方案:https://www.cnblogs.com/weixuqin/p/7029177.html

  9. C语言-错误处理

    标记程序的运行状态和控制主要有以下几种:break/continue/return/参数的返回值/exit(int n)_exit() atexit((*p)(参数列表)): 1 break:用在开关 ...

  10. ios 物流时间轴,自动匹配电话号码,可点击拨打

    http://www.code4app.com/thread-27587-1-1.html 资讯时间轴(折叠/展开) http://www.code4app.com/thread-32358-1-1. ...