日期:2014-05-16  浏览次数:20802 次

Shiro和AJAX完美整合

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, 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(messa