ShiroAJAX完美整合

这是我第一次认认真真写博客,以前为了图快,结果写下来基本只有自己可以看懂。不过我感觉有经验就应该要和别人分享下,在分享的同时或许可以为这个问题找到更好的解决方案。

我在上学期5月份学完了Shiro,当初学时,看了半天的英文文档,最后还是不知道它为什么要这么干,只知道很多人说它很方便。在今年9月初时,我在次使用它,这次终于知道它的内部原理,但是感觉它的处理方式和我的上一个项目很相似。

这个为了实现远程服务器管理平台,我用上了Shiro,不过给我的第一个感觉是为什么它老是不按照我的业务方式来。最主要的是它在处理非法请求时,不是返回错误的字符串,而是直接跳转到登入界面,这个对于使用ajax来说简直是个噩耗。针对这个问题网上也有很多解决方案,我记得最清楚的是有一个人他把登入的地址改成json字符串,对于这个方案,我只能说不够灵活。算了,不说那么多了,直接说我的解决方案。

Shiro最主要的是拦截器,所以我们只要重写个拦截器就可以达到我们的目的,不管是直接请求还是ajax请求都可以直接处理。shiro处理拦截的类主要是FormAuthenticationFilter,所以我们对里面相应的方法进行重写即可。

/**
 * 
 */
package com.wms.studio.filter;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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;

/**
 * @author WMS
 * 
 */
public class CaptchaFormAuthenticationFilter extends FormAuthenticationFilter {

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

	/*
	 *	主要是针对登入成功的处理方法。对于请求头是AJAX的之间返回JSON字符串。
	 */
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token,Subject subject,ServletRequest request,ServletResponse response)
			throws Exception {
		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;
	}

	/**
	 * 主要是处理登入失败的方法
	 */
	@Override
	protected boolean onLoginFailure(AuthenticationToken token,AuthenticationException e,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;
	}

	/**
	 * 所有请求都会经过的方法。
	 */
	@Override
	protected boolean onAccessDenied(ServletRequest request,ServletResponse response) throws Exception {

		if (isLoginRequest(request,response)) {
			if (isLoginSubmission(request,response)) {
				if (log.isTraceEnabled()) {
					log.trace("Login submission detected.  Attempting to execute login.");
				}
				if ("XMLHttpRequest"
						.equalsIgnoreCase(((HttpServletRequest) request)
								.getHeader("X-Requested-With"))) {// 不是ajax请求
					String vcode = request.getParameter("vcode");
					HttpServletRequest httpservletrequest = (HttpServletRequest) request;
					String vvcode = (String) httpservletrequest
							.getSession()
							.getAttribute(
									com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
					if (vvcode == null || "".equals(vvcode)
							|| !vvcode.equals(vcode)) {
						response.setCharacterEncoding("UTF-8");
						PrintWriter out = response.getWriter();
						out.println("{success:false,message:'验证码错误'}");
						out.flush();
						out.close();
						return false;
					}
				}
				return executeLogin(request,response);
			} else {
				if (log.isTraceEnabled()) {
					log.trace("Login page view.");
				}
				// allow them to see the login page ;)
				return true;
			}
		} else {
			if (log.isTraceEnabled()) {
				log.trace("Attempting to access a path which requires authentication.  Forwarding to the "
						+ "Authentication url [" + getLoginUrl() + "]");
			}
			if (!"XMLHttpRequest"
					.equalsIgnoreCase(((HttpServletRequest) request)
							.getHeader("X-Requested-With"))) {// 不是ajax请求
				saveRequestAndRedirectToLogin(request,response);
			} else {
				response.setCharacterEncoding("UTF-8");
				PrintWriter out = response.getWriter();
				out.println("{message:'login'}");
				out.flush();
				out.close();
			}
			return false;
		}
	}
}

然后还需要告诉拦截器,你定义了这个拦截。

<!-- Shiro Filter -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterfactorybean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/login.jsp" />
		<!-- <property name="successUrl" value="/" /> -->
		<property name="filters">
			<map>
				<entry key="authc">
					<bean class="com.wms.studio.filter.CaptchaFormAuthenticationFilter"></bean>
				</entry>
			</map>
		</property>
		<property name="filterChainDeFinitions">
			<value>
				/extjs/** = anon
				/js/userservice.js= anon
				/resources/**=anon
				/kaptcha.jpg=anon
				/**=authc
			</value>
		</property>
	</bean>

这样基本就可以实现完美整合了。。。。。。。。。

看看我的效果图

例子下载地址:http://download.csdn.net/detail/wu560130911/6295521


不懂或有问题的可以联系我,E-mail:560130911@163.com。

Shiro和AJAX完美整合的更多相关文章

  1. IOs Cordova长按显示文本选择放大镜即使禁用文本选择,如何删除?

    是否有任何可能导致此问题的插件?任何帮助深表感谢.Cordova插件:>com.mbppower.camerapreview>cordova-plugin-statusbar>cordova-plugin-whitelist>离子插件键盘>org.apache.cordova.camera>org.apache.cordova.console>org.apache.cordova.device>org.apache.cordova.dialogs>org.apache.cordova.file>org.a

  2. 应用程序关闭时的iOS任务

    我正在构建一个应用程序,通过ajax将文件上传到服务器.问题是用户很可能有时不会有互联网连接,并且客户希望在用户重新连接时安排ajax调用.这可能是用户在离线时安排文件上传并关闭应用程序.应用程序关闭时可以进行ajax调用吗?

  3. android – org.apache.cordova.api不存在. PhoneGap 3.0

    我正在尝试将VideoPlayer插件(https://github.com/macdonst/VideoPlayer)添加到我的phonegapAndroid应用程序中.在编译时遇到问题:第25行:解决方法将您的导入更改为:

  4. 如何将android客户端连接到我的笔记本电脑内的Apache服务器(php)的localhost?

    我的笔记本电脑中的localhost-127.0.0.1或android10.0.0.1中的localhost?>那么,如果我想从android访问localhost来调用PHP来运行?哪个ip地址/url我需要放在Android应用程序?我需要在httpconfig中为XAMPP修改任何内容吗?解决方法使用ipconfig在笔记本电脑中找到您的IP地址.在手机中使用该地址而不是127.0.0.1.

  5. android – 在android工作室中的proguard错误

    我想在我的应用程序中使用proguard,我启用它但是当我想生成apk文件时,它给了我这个错误:我正在使用最新版本的sdk23,这是我的gradle文件:怎么了?我在这段代码中做错了什么?谢谢解决方法只需在proguard上添加:

  6. 无法修复Android Proguard返回错误代码1错误

    当我尝试在我的Android应用程序中使用proguard时只需添加到我的project.properties文件,APK导出失败并显示消息Proguard返回错误代码1这是我的project.properties文件这是错误堆栈:解决方法将这些行添加到proguard配置文件(proguard-android.txt)见ProguardTroubleshooting请注意,如果您使用您的配置文件

  7. Phonegap 2.4 Android Proguard配置

    有人有主意吗???

  8. android – 如何在sharedPreferences中分析ANR

    在sharedPreferences中遇到ANR,不知道如何定位问题.以下是trace的三个部分,其他大多数线程都是“WAIT”或“TIMED_WAIT”.由于countdownlatch.await(),“主”线程被阻止.第二个线程“pool-1-thread-1”等待fsync.最后一个是试图读一些东西.我认为第二个线程已经阻塞了主线程,因为如果这个无法完成,它将不会调用countdownla

  9. Android无法访问org.apache.http.client.HttpClient

    我正在使用androidstudio创建一个向服务器发出GET请求的应用程序.我的代码是这样的:问题是AndroidStudio标记了这一行有错误:说“无法访问org.apache.http.client.HttpClient”这是我的gradle文件:解决方法在AndroidSDK23中不推荐使用HttpClient,因为它推断,您可以在HttpURLConnection中迁移代码https:/

  10. android – Phonegap本地构建 – jquery ajax错误:readystate 0 responsetext status 0 statustext error

    解决方法您是否在索引文件中包含了内容安全元标记?

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部