Shiro和AJAX完美整合

来源:互联网 发布:2015年进出口贸易数据 编辑:程序博客网 时间:2024/06/05 23:44

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字符串。 */@Overrideprotected 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;}/** * 主要是处理登入失败的方法 */@Overrideprotected 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 blocke1.printStackTrace();}return false;}/** * 所有请求都会经过的方法。 */@Overrideprotected 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。

原创粉丝点击