shiro + extjs

来源:互联网 发布:阿里云域名独立管理 编辑:程序博客网 时间:2024/04/28 16:25

源码下载 我的GITHUB

shiro 相比与spring security配置上简单很多。


加载shiro config

    <context-param>        <param-name>contextConfigLocation</param-name>        <param-value>           classpath:shiro-config.xml        </param-value>    </context-param>

添加shrio过滤器,这里需要注意的是,过滤器的名字shiroFilter必须与配置文件里面的bean名字相同

<filter>    <filter-name>shiroFilter</filter-name>    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>    <init-param>        <param-name>targetFilterLifecycle</param-name>        <param-value>true</param-value>    </init-param></filter><filter-mapping>    <filter-name>shiroFilter</filter-name>    <url-pattern>/*</url-pattern></filter-mapping>


shiroFilter配置,这里需要配置一个 formAuthenticationFilter,作用在后面会提到,主要是因为extjs的ajax请求。

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><!-- override these for application-specific URLs if you like:--><property name="loginUrl" value="/login.html"/>    <property name="successUrl" value="/index.html"/>    <property name="unauthorizedUrl" value="/unauthorized.html"/>    <property name="filters">        <util:map>            <entry key="authc" value-ref="formAuthenticationFilter"/>        </util:map>    </property>    <property name="filterChainDefinitions">    <value>    /comp/** = anon    /pages/** = anon    /resources/** = anon    /view/** = anon    /** = authc    </value>    </property></bean>

shiroFilter中引用了 securityManageer。如果参考shiro官网的同学请注意,官网documentation中的manager是org.apache.shiro.mgt.DefaultWebSecurityManager。在1.2.2中,这个类是没有实现WebSecurityManager的,所以会跑出unimplement WebSecurityManager的异常。

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">    <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. 如果有多个realm,需要用reamls参数,为实践。-->    <property name="realm" ref="fastRealm"/>    </bean>


引用的realm是可以重写的。

<bean id="fastRealm" class="com.chinadreamer.contacts.filter.shiro.UserRealm"></bean>
重写realm。

重写的doGetAuthorizationInfo与doGetAuthenticationInfo在官网中已经很明确的说明了,这里不再解释。

我说下这里会遇到的一个问题。shiro跟spring的filter并没有优先级之分,而用户验证,一般都会涉及到datasource bean的引用,比方这里的userservice。所以需要注意的是必须在spring bean加载之后,进入shiro,否则是无法加载的。

我的做法是在applicationContext.xml 结尾才引入shiro-config.xml,这样就可以获取到bean了。

引入方式比较常规

<import resource="shiro-config.xml"/>

public class UserRealm extends AuthorizingRealm{private final static Logger LOGGER = Logger.getLogger(UserRealm.class);@Autowiredprivate UserService userService;public UserRealm(){super();LOGGER.info(" init user realm ");setAuthenticationTokenClass(UsernamePasswordToken.class);}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {User user = ShiroUtils.getUser();        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();        return authorizationInfo;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {UsernamePasswordToken upToken = (UsernamePasswordToken) token;        String username = upToken.getUsername();        String password = new String(upToken.getPassword());        User user;        try {user = this.userService.userLogin(username, password);} catch (Exception e) {throw new AuthenticationException(e.getMessage(),e);}        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password.toCharArray(), getName());return info;}}

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

简单的shiro到这就可以了。但是如果配合extjs,就需要控制ajax返回,大家知道extj是根据response会写的success 字段来判断的。

    <!--替换默认的form 验证过滤器-->    <bean id="formAuthenticationFilter" class="com.chinadreamer.contacts.filter.shiro.FastFormAuthenticationFilter">    </bean>

提供一份源码,根据各自的需求改动,这是其他大大提供的。

package com.chinadreamer.contacts.filter.shiro;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.log4j.Logger;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;public class FastFormAuthenticationFilter extends FormAuthenticationFilter{private static final Logger LOGGER =  Logger.getLogger(FastFormAuthenticationFilter.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;}/**      * 主要是处理登入失败的方法      */      @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;      }          /**      * 所有请求都会经过的方法。      */      @Override      protected boolean onAccessDenied(ServletRequest request,              ServletResponse response) throws Exception {            if (isLoginRequest(request, response)) {              if (isLoginSubmission(request, response)) {                  if (LOGGER.isTraceEnabled()) {                  LOGGER.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 (LOGGER.isTraceEnabled()) {                  LOGGER.trace("Login page view.");                  }                  // allow them to see the login page ;)                  return true;              }          } else {              if (LOGGER.isTraceEnabled()) {              LOGGER.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("{success:true,message:'login'}");  //                out.flush();  //                out.close();                  return true;            }              return false;          }      }  }




0 0
原创粉丝点击