Shiro的Web项目配置(转)

Shiro的Web项目配置

一 shiro的学习

二 shiro的java客户端配置

三 关于权限的一些问题

一 shiro的学习

官网和张开涛博客

二 shiro的java客户端配置

1.在web.xml中配置shiro的过滤器

[java] view plain copy
?
  1. <!-- shiro 安全过滤器 -->  
  2. <!-- The filter-name matches name of a 'shiroFilter' bean inside  -->  
  3. <filter>  
  4.     <filter-name>shiroFilter</filter-name>  
  5.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  6.     <async-supported>true</async-supported>  
  7.     <init-param>  
  8.         <param-name>targetFilterLifecycle</param-name>  
  9.         <param-value>true</param-value>  
  10.     </init-param>  
  11. </filter>  
  12. <filter-mapping>  
  13.     <filter-name>shiroFilter</filter-name>  
  14.     <url-pattern>/*</url-pattern>  
  15. </filter-mapping>  
同时在web.xml读取shiro的配置文件

Shiro的Web项目配置(转)

2.在spring-shiro-web.xml中配置:

[java] view plain copy
?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:util="http://www.springframework.org/schema/util"  
  4.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.        xmlns:context="http://www.springframework.org/schema/context"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">  
  8.   
  9. <!--     为了获取adminPath的值 -->  
  10.     <context:property-placeholder ignore-unresolvable="true" location="classpath*:/system.properties"/>  
  11.   
  12.     <!-- 配置安全管理中心,Shiro的主要业务层对象基于web的应用程序 -->  
  13.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  14.         <property name="realm" ref="userRealm"/>  
  15.     </bean>  
  16.       
  17. <!--     自定义的过滤器,用来验证登陆 -->  
  18.     <bean id="formAuthenticationCaptchaFilter" class="com.huaxia.shiro.FormAuthenticationCaptchaFilter">  
  19.         <property name="usernameParam" value="username"/>  
  20.         <property name="passwordParam" value="password"/>  
  21.         <property name="captchaParam" value="captcha"/>  
  22.         <property name="loginUrl" value="${adminPath}/login"/>  
  23.     </bean>  
  24. <!--     自定义的过滤器 -->  
  25.     <bean id="userFilter" class="com.huaxia.shiro.HuaXiaUserFilter">  
  26.     </bean>  
  27.   
  28. <!-- Shiro的Web过滤器,在web.xml中配置的shiroFilter即指向此 -->  
  29.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  30. <!--         指定一个安全管理中心,用来验证用户能否登陆和相关权限 -->  
  31.         <property name="securityManager" ref="securityManager"/>  
  32. <!--         所有地址被重定向到该地址 -->  
  33.         <property name="loginUrl" value="${adminPath}/login"/>  
  34. <!--         用户登录成功后的页面地址 -->  
  35.         <property name="successUrl" value="${adminPath}"/>  
  36. <!--         过滤器链,在shiroFilter之前即开始执行 -->  
  37.         <property name="filters">  
  38.             <util:map>  
  39.                 <entry key="authc" value-ref="formAuthenticationCaptchaFilter"/>  
  40.                 <entry key="user" value-ref="userFilter"/>  
  41.             </util:map>  
  42.         </property>  
  43. <!--         配置地址对应的过滤器 -->  
  44.         <property name="filterChainDefinitions">  
  45.             <value>  
  46.                 ${adminPath}/login = authc  
  47.                 /** = user  
  48.             </value>  
  49.         </property>  
  50.     </bean>  
  51.   
  52.   
  53.     <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
  54.     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  
  55.   
  56.     <!-- 下面两个bean是shiro官网推荐的配置  -->  
  57.       
  58.     <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">  
  59.         <property name="proxyTargetClass" value="true" />  
  60.     </bean>  
  61.     <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
  62.         <property name="securityManager" ref="securityManager"/>  
  63.     </bean>  
  64. </beans>  

其中UserRealm的实现如下:

[java] view plain copy
?
  1. package com.huaxia.shiro;  
  2.   
  3.   
  4. import javax.annotation.PostConstruct;  
  5.   
  6. import org.apache.shiro.SecurityUtils;  
  7. import org.apache.shiro.authc.AuthenticationException;  
  8. import org.apache.shiro.authc.AuthenticationInfo;  
  9. import org.apache.shiro.authc.AuthenticationToken;  
  10. import org.apache.shiro.authc.DisabledAccountException;  
  11. import org.apache.shiro.authc.LockedAccountException;  
  12. import org.apache.shiro.authc.SimpleAuthenticationInfo;  
  13. import org.apache.shiro.authc.UnknownAccountException;  
  14. import org.apache.shiro.authc.credential.HashedCredentialsMatcher;  
  15. import org.apache.shiro.authz.AuthorizationInfo;  
  16. import org.apache.shiro.authz.SimpleAuthorizationInfo;  
  17. import org.apache.shiro.realm.AuthorizingRealm;  
  18. import org.apache.shiro.subject.PrincipalCollection;  
  19. import org.apache.shiro.util.ByteSource;  
  20. import org.slf4j.Logger;  
  21. import org.slf4j.LoggerFactory;  
  22. import org.springframework.beans.factory.annotation.Autowired;  
  23. import org.springframework.stereotype.Service;  
  24.   
  25. import com.google.code.kaptcha.Constants;  
  26. import com.huaxia.Constant;  
  27. import com.huaxia.common.utils.security.Digests;  
  28. import com.huaxia.common.utils.security.Encodes;  
  29. import com.huaxia.user.entity.User;  
  30. import com.huaxia.user.service.UserService;  
  31.   
  32.   
  33. @Service  
  34. public class UserRealm extends AuthorizingRealm {  
  35.     private Logger logger = LoggerFactory.getLogger(UserRealm.class);  
  36.   
  37.     @Autowired  
  38.     private UserService userService;  
  39.   
  40.     @Override  
  41.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
  42.         String username = (String)principals.getPrimaryPrincipal();  
  43.   
  44.         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();  
  45.         authorizationInfo.setRoles(userService.findRoles(username));  
  46.         authorizationInfo.setStringPermissions(userService.findPermissions(username));  
  47.   
  48.         return authorizationInfo;  
  49.     }  
  50.   
  51.     @Override  
  52.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {  
  53.         UsernamePasswordCaptchaToken captchaToken = (UsernamePasswordCaptchaToken) token;  
  54.         String username = String.valueOf(token.getPrincipal());  
  55.         User user = userService.findByUsername(username,Constant.USER_DELFLAG);  
  56.         if(null != user && doCaptchValidate(captchaToken)) {  
  57.             if (Boolean.TRUE.equals(user.getLocked())) {  
  58.                 throw new LockedAccountException(); //帐号锁定  
  59.             }  
  60.             if(Constant.LOGIN_STATUS_N.equals(user.getLoginStatus())){  
  61.                 throw new DisabledAccountException();  
  62.             }  
  63.             byte[] salt = Encodes.decodeHex(user.getSalt());  
  64.             //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,可以自定义实现  
  65.             SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(  
  66.                     user.getUserName(),  
  67.                     user.getPassword(), //密码  
  68.                     ByteSource.Util.bytes(salt),  
  69.                     getName()  //realm name  
  70.             );  
  71.             //SecurityUtils.getSubject().getSession().setAttribute("user", user);  
  72.             SecurityUtils.getSubject().getSession().setAttribute("userId", user.getUserId());  
  73.             userService.updateByLogin(user);  
  74.             return authenticationInfo;  
  75.         }else{  
  76.             throw new UnknownAccountException();  
  77.         }  
  78.     }  
  79.   
  80.     protected boolean doCaptchValidate(UsernamePasswordCaptchaToken token){  
  81.         String captcha = (String) SecurityUtils.getSubject().getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);  
  82.         if(captcha != null && !captcha.equalsIgnoreCase(token.getCaptcha())){  
  83.             throw new CaptchaException("Code error");  
  84.         }  
  85.         return true;  
  86.     }  
  87.   
  88.     @PostConstruct  
  89.     public void initCredentialsMatcher() {  
  90.         HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(Digests.SHA1);  
  91.         matcher.setHashIterations(Constant.HASH_INTERATIONS);  
  92.         setCredentialsMatcher(matcher);  
  93.     }  
  94.   
  95.     @Override  
  96.     public void clearCachedAuthorizationInfo(PrincipalCollection principals) {  
  97.         super.clearCachedAuthorizationInfo(principals);  
  98.     }  
  99.   
  100.     @Override  
  101.     public void clearCachedAuthenticationInfo(PrincipalCollection principals) {  
  102.         super.clearCachedAuthenticationInfo(principals);  
  103.     }  
  104.   
  105.     @Override  
  106.     public void clearCache(PrincipalCollection principals) {  
  107.         super.clearCache(principals);  
  108.     }  
  109.   
  110.     public void clearAllCachedAuthorizationInfo() {  
  111.         getAuthorizationCache().clear();  
  112.     }  
  113.   
  114.     public void clearAllCachedAuthenticationInfo() {  
  115.         getAuthenticationCache().clear();  
  116.     }  
  117.   
  118.     public void clearAllCache() {  
  119.         clearAllCachedAuthenticationInfo();  
  120.         clearAllCachedAuthorizationInfo();  
  121.     }  
  122. }  
其中formAuthenticationCaptchaFilter的实现如下:

[java] view plain copy
?
  1. package com.huaxia.shiro;  
  2.   
  3. import javax.servlet.ServletRequest;  
  4. import javax.servlet.ServletResponse;  
  5. import javax.servlet.http.HttpServletRequest;  
  6. import javax.servlet.http.HttpServletResponse;  
  7.   
  8. import org.apache.shiro.authc.AuthenticationToken;  
  9. import org.apache.shiro.subject.Subject;  
  10. import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;  
  11. import org.apache.shiro.web.util.WebUtils;  
  12. import org.slf4j.Logger;  
  13. import org.slf4j.LoggerFactory;  
  14.   
  15.   
  16. public class FormAuthenticationCaptchaFilter extends FormAuthenticationFilter {  
  17.   
  18.     private Logger logger = LoggerFactory.getLogger(FormAuthenticationCaptchaFilter.class);  
  19.   
  20.     public static final String DEFAULT_CAPTCHA_PARAM = "captcha";  
  21.     private String captchaParam = DEFAULT_CAPTCHA_PARAM;  
  22.   
  23.     public String getCaptchaParam() {  
  24.         return captchaParam;  
  25.     }  
  26.   
  27.     public void setCaptchaParam(String captchaParam){  
  28.         this.captchaParam = captchaParam;  
  29.     }  
  30.   
  31.     protected String getCaptcha(ServletRequest request) {  
  32.         return WebUtils.getCleanParam(request, getCaptchaParam());  
  33.     }  
  34.   
  35.     protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {  
  36.         String username = getUsername(request) == null ? "" : getUsername(request);  
  37.         String password = getPassword(request) == null ? "" : getPassword(request);  
  38.         String captcha = getCaptcha(request) == null ? "" : getCaptcha(request);  
  39.         boolean rememberMe = isRememberMe(request);  
  40.         return new UsernamePasswordCaptchaToken(username,password.toCharArray(), rememberMe, captcha);  
  41.     }  
  42.   
  43.   
  44.   
  45.     @Override  
  46.     protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,  
  47.                                      ServletRequest request, ServletResponse response) throws Exception {  
  48.         //      issueSuccessRedirect(request, response);  
  49.         //      we handled the success redirect directly, prevent the chain from continuing:  
  50.         HttpServletRequest httpServletRequest = (HttpServletRequest)request;  
  51.         HttpServletResponse httpServletResponse = (HttpServletResponse)response;  
  52.   
  53.   
  54.         if (!"XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))  
  55.                 || request.getParameter("ajax") == null) {// 不是ajax请求  
  56.             httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + this.getSuccessUrl());  
  57.         } else {  
  58.             httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + this.getSuccessUrl());  
  59.         }  
  60.   
  61.         return false;  
  62.     }  
  63.   
  64.   
  65.   
  66.   
  67. }  
其中HuaXiaUserFilter的实现如下:

[java] view plain copy
?
  1. package com.huaxia.shiro;  
  2.   
  3. import org.apache.shiro.web.filter.authc.UserFilter;  
  4. import org.apache.shiro.web.filter.session.NoSessionCreationFilter;  
  5. import org.apache.shiro.web.util.WebUtils;  
  6.   
  7. import javax.servlet.ServletRequest;  
  8. import javax.servlet.ServletResponse;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. public class HuaXiaUserFilter extends UserFilter {  
  12.   
  13.     @Override  
  14.     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {  
  15.   
  16.         /*if(!"XMLHttpRequest".equalsIgnoreCase(WebUtils.toHttp(response).getHeader("X-Requested-With")) 
  17.                 || request.getParameter("ajax") == null ){ 
  18.             this.saveRequestAndRedirectToLogin(request, response); 
  19.         }else{*/  
  20.             HttpServletResponse res = WebUtils.toHttp(response);  
  21.             res.setHeader("sessionstatus","timeout");  
  22.             //res.sendError(HttpServletResponse.SC_UNAUTHORIZED);  
  23.        /* }*/  
  24.         this.saveRequestAndRedirectToLogin(request, response);  
  25.   
  26.         return false;  
  27.     }  
  28.   
  29. }  
3.另外在Mvc的配置文件spring-mvc.xml中加入如下拦截器内容:
[java] view plain copy
?
  1. <aop:config proxy-target-class="true"></aop:config>  
  2. <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
  3.     <property name="securityManager" ref="securityManager"/>  
  4. </bean>  
[java] view plain copy
?
  1.   

三 关于权限的一些问题

1.shiro如何实现验证码?

关于shiro的验证码,使用的是google的kaptcha , 在web.xml中配置sevlet如下:

[java] view plain copy
?
  1. <servlet>  
  2.     <servlet-name>ImageServlet</servlet-name>  
  3.     <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>  
  4. </servlet>  
  5.   
  6. <servlet-mapping>  
  7.     <servlet-name>ImageServlet</servlet-name>  
  8.     <url-pattern>/ImageServlet</url-pattern>  
  9. </servlet-mapping>