ssm+freemark集成shiro

来源:互联网 发布:jq22 bomb.js 编辑:程序博客网 时间:2024/05/22 05:24


1.导入的jar包

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <!-- shiro start -->  
  2. <!-- freemarker + shiro(标签) begin -->  
  3. <dependency>  
  4.     <groupId>net.mingsoft</groupId>  
  5.     <artifactId>shiro-freemarker-tags</artifactId>  
  6.     <version>0.1</version>  
  7. </dependency>  
  8. <!-- freemarker + shiro(标签) end -->  
  9. <dependency>    
  10.        <groupId>org.apache.shiro</groupId>    
  11.        <artifactId>shiro-core</artifactId>    
  12.    </dependency>    
  13.    <dependency>    
  14.        <groupId>org.apache.shiro</groupId>    
  15.        <artifactId>shiro-web</artifactId>    
  16.    </dependency>    
  17.    <dependency>    
  18.        <groupId>org.apache.shiro</groupId>    
  19.        <artifactId>shiro-ehcache</artifactId>    
  20.    </dependency>    
  21.    <dependency>    
  22.        <groupId>org.apache.shiro</groupId>    
  23.        <artifactId>shiro-spring</artifactId>    
  24.    </dependency>  
  25.    <!-- shiro end -->  
2.在web.xml中加入shiro filter

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <!--Shiro过滤器-->  
  2. <filter>  
  3.     <filter-name>shiroFilter</filter-name>  
  4.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  5.     <init-param>  
  6.         <param-name>targetFilterLifecycle</param-name>  
  7.         <param-value>true</param-value>  
  8.     </init-param>  
  9. </filter>  
  10. <filter-mapping>  
  11.     <filter-name>shiroFilter</filter-name>  
  12.     <url-pattern>/*</url-pattern>  
  13.     <dispatcher>REQUEST</dispatcher>  
  14.     <dispatcher>FORWARD</dispatcher>  
  15. </filter-mapping>  
此过滤器要放在第一个,且名称要与spring-shiro,xml中shiro filter一致

3.在freemarker中加入shiro标签

3.1新建一个FreeMarkerConfigExtend类继承FreeMarkerConfigurer,

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.business.util;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;  
  6.   
  7. import com.jagregory.shiro.freemarker.ShiroTags;  
  8.   
  9. import freemarker.template.Configuration;  
  10. import freemarker.template.TemplateException;  
  11.   
  12. public class FreeMarkerConfigExtend extends FreeMarkerConfigurer {  
  13.       
  14.     @Override    
  15.     public void afterPropertiesSet() throws IOException, TemplateException {    
  16.         super.afterPropertiesSet();  
  17.         Configuration cfg = this.getConfiguration();  
  18.         cfg.setSharedVariable("shiro"new ShiroTags());//shiro标签  
  19.         cfg.setNumberFormat("#");//防止页面输出数字,变成2,000  
  20.         //可以添加很多自己的要传输到页面的[方法、对象、值]  
  21.           
  22.           
  23.         /* 
  24.          * 在controller层使用注解再加一层判断 
  25.          * 注解 @RequiresPermissions("/delete") 
  26.          */  
  27.           
  28.         /*shiro标签*/  
  29.         /** 
  30.         1.游客 
  31.         <@shiro.guest>   
  32.             您当前是游客,<a href="javascript:void(0);" class="dropdown-toggle qqlogin" >登录</a> 
  33.         </@shiro.guest>  
  34.          
  35.         2.user(已经登录,或者记住我登录) 
  36.         <@shiro.user>   
  37.             欢迎[<@shiro.principal/>]登录,<a href="/logout.shtml">退出</a>   
  38.         </@shiro.user>    
  39.  
  40.         3.authenticated(已经认证,排除记住我登录的) 
  41.         <@shiro.authenticated>   
  42.             用户[<@shiro.principal/>]已身份验证通过   
  43.         </@shiro.authenticated>            
  44.          
  45.         4.notAuthenticated(和authenticated相反) 
  46.         <@shiro.notAuthenticated> 
  47.                   当前身份未认证(包括记住我登录的) 
  48.         </@shiro.notAuthenticated>  
  49.          
  50.         5.principal标签(能够取到你在realm中保存的信息比如我存的是ShiroUser对象,取出其中urlSet属性) 
  51.         <!--需要指定property--> 
  52.         <@shiro.principal property="urlSet"/> 
  53.          
  54.         6.hasRole标签(判断是否拥有这个角色) 
  55.         <@shiro.hasRole name="admin">   
  56.             用户[<@shiro.principal/>]拥有角色admin<br/>   
  57.         </@shiro.hasRole>  
  58.          
  59.         7.hasAnyRoles标签(判断是否拥有这些角色的其中一个) 
  60.         <@shiro.hasAnyRoles name="admin,user,member">   
  61.             用户[<@shiro.principal/>]拥有角色admin或user或member<br/>   
  62.         </@shiro.hasAnyRoles>  
  63.          
  64.         8.lacksRole标签(判断是否不拥有这个角色) 
  65.         <@shiro.lacksRole name="admin">   
  66.             用户[<@shiro.principal/>]不拥有admin角色 
  67.         </@shiro.lacksRole>  
  68.          
  69.         9.hasPermission标签(判断是否有拥有这个权限) 
  70.         <@shiro.hasPermission name="user:add">   
  71.             用户[<@shiro.principal/>]拥有user:add权限 
  72.         </@shiro.hasPermission> 
  73.          
  74.         10.lacksPermission标签(判断是否没有这个权限) 
  75.         <@shiro.lacksPermission name="user:add">   
  76.             用户[<@shiro.principal/>]不拥有user:add权限 
  77.         </@shiro.lacksPermission>  
  78.          
  79.         **/  
  80.     }    
  81. }  
3.2修改spring-mvc-servlet.xml中的freemarker配置


4.新建CustomCredentialsMatcher类继承shiro的SimpleCredentialsMatcher类,这个类作用是自定义密码验证

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.business.shiro;  
  2.   
  3. import org.apache.shiro.authc.AuthenticationInfo;  
  4. import org.apache.shiro.authc.AuthenticationToken;  
  5. import org.apache.shiro.authc.UsernamePasswordToken;  
  6. import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;  
  7.   
  8. import com.business.util.MD5Util;  
  9.   
  10. /**  
  11.  * Description: 告诉shiro如何验证加密密码,通过SimpleCredentialsMatcher或HashedCredentialsMatcher  
  12.  * @Author: zh  
  13.  * @Create Date: 2017-5-9  
  14.  */    
  15.     
  16. public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {    
  17.         
  18.     @Override     
  19.     public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {      
  20.                
  21.         UsernamePasswordToken token = (UsernamePasswordToken) authcToken;   
  22.           
  23.           
  24.         Object tokenCredentials = MD5Util.hmac_md5(String.valueOf(token.getPassword()));  
  25.         Object accountCredentials = getCredentials(info);  
  26.         //将密码加密与系统加密后的密码校验,内容一致就返回true,不一致就返回false  
  27.         return equals(tokenCredentials, accountCredentials);  
  28.     }    
  29.       
  30. }  
5.新建ShiroDbRealm类
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.business.shiro;  
  2.   
  3. import java.util.List;  
  4. import java.util.Set;  
  5.   
  6. import javax.annotation.PostConstruct;  
  7.   
  8. import org.apache.log4j.Logger;  
  9. import org.apache.shiro.authc.AuthenticationException;  
  10. import org.apache.shiro.authc.AuthenticationInfo;  
  11. import org.apache.shiro.authc.AuthenticationToken;  
  12. import org.apache.shiro.authc.DisabledAccountException;  
  13. import org.apache.shiro.authc.SimpleAuthenticationInfo;  
  14. import org.apache.shiro.authc.UsernamePasswordToken;  
  15. import org.apache.shiro.authc.credential.CredentialsMatcher;  
  16. import org.apache.shiro.authz.AuthorizationInfo;  
  17. import org.apache.shiro.authz.SimpleAuthorizationInfo;  
  18. import org.apache.shiro.cache.CacheManager;  
  19. import org.apache.shiro.realm.AuthorizingRealm;  
  20. import org.apache.shiro.subject.PrincipalCollection;  
  21. import org.apache.shiro.subject.SimplePrincipalCollection;  
  22. import org.springframework.beans.factory.annotation.Autowired;  
  23.   
  24. import com.business.dao.UserDao;  
  25. import com.business.entity.Menu;  
  26. import com.business.entity.Role;  
  27. import com.business.entity.User;  
  28. import com.business.entity.UserRole;  
  29. import com.business.service.sysService.MenuService;  
  30. import com.business.service.sysService.RoleService;  
  31. import com.business.service.sysService.UserRoleService;  
  32. import com.business.service.sysService.UserService;  
  33. import com.business.util.SessionUtil;  
  34. import com.common.util.BizUtil;  
  35. import com.google.common.collect.Sets;  
  36.   
  37. /** 
  38.  * @description:shiro权限认证 
  39.  * @author:zhanghao 
  40.  * @date:2017/5/8 14:51 
  41.  */  
  42. public class ShiroDbRealm extends AuthorizingRealm {  
  43.     private static final Logger LOGGER = Logger.getLogger(ShiroDbRealm.class);  
  44.   
  45.     @Autowired private UserService userService;  
  46.     @Autowired private UserDao userDao;  
  47.     @Autowired private RoleService roleService;  
  48.     @Autowired private UserRoleService userRoleService;  
  49.     @Autowired private MenuService menuService;  
  50.       
  51.     public ShiroDbRealm(CacheManager cacheManager, CredentialsMatcher matcher) {  
  52.         super(cacheManager, matcher);  
  53.     }  
  54.       
  55.     /** 
  56.      * Shiro登录认证(原理:用户提交 用户名和密码  --- shiro 封装令牌 ---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制 ) 
  57.      */  
  58.     @Override  
  59.     protected AuthenticationInfo doGetAuthenticationInfo(  
  60.             AuthenticationToken authcToken) throws AuthenticationException {  
  61.         LOGGER.info("Shiro开始登录认证");  
  62.         UsernamePasswordToken token = (UsernamePasswordToken) authcToken;  
  63.         User user = userDao.getByName(token.getUsername());  
  64.         // 账号不存在  
  65.         if (user == null) {  
  66.             return null;  
  67.         }  
  68.         // 账号未启用  
  69.         if (user.getStatus() == 1) {  
  70.             throw new DisabledAccountException();  
  71.         }  
  72.         //将用户信息保存在session中  
  73.         SessionUtil.addSession(user);  
  74.         UserRole userRole = userRoleService.getByUserId(user.getId());  
  75.         Role role = roleService.getById(userRole.getRoleId());  
  76.         // 读取用户的url和角色  
  77.         Set<String> roles = Sets.newHashSet(role.getName());  
  78.         List<Long> menuIds = BizUtil.stringToLongList(role.getMenu(), ",");  
  79.         List<Menu> menuList = menuService.getListByIds(menuIds);  
  80.         List<String> menuStr = BizUtil.extractToList(menuList, "url");  
  81.           
  82.         Set<String> urls = Sets.newHashSet(menuStr);  
  83.         urls.remove("");  
  84.         urls.remove(null);  
  85.           
  86.         ShiroUser shiroUser = new ShiroUser(user.getId(), user.getLoginName(), user.getUsername(), urls);  
  87.         shiroUser.setRoles(roles);  
  88.         // 认证缓存信息  
  89.         return new SimpleAuthenticationInfo(shiroUser, user.getPassword().toCharArray(),getName());  
  90.     }  
  91.   
  92.     /** 
  93.      * Shiro权限认证 
  94.      */  
  95.     @Override  
  96.     protected AuthorizationInfo doGetAuthorizationInfo(  
  97.             PrincipalCollection principals) {  
  98.         ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();  
  99.           
  100.         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
  101.         info.setRoles(shiroUser.getRoles());  
  102.         info.addStringPermissions(shiroUser.getUrlSet());  
  103.           
  104.         return info;  
  105.     }  
  106.       
  107.     @Override  
  108.     public void onLogout(PrincipalCollection principals) {  
  109.         super.clearCachedAuthorizationInfo(principals);  
  110.         ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();  
  111.         removeUserCache(shiroUser);  
  112.     }  
  113.   
  114.     /** 
  115.      * 清除用户缓存 
  116.      * @param shiroUser 
  117.      */  
  118.     public void removeUserCache(ShiroUser shiroUser){  
  119.         removeUserCache(shiroUser.getLoginName());  
  120.     }  
  121.   
  122.     /** 
  123.      * 清除用户缓存 
  124.      * @param loginName 
  125.      */  
  126.     public void removeUserCache(String loginName){  
  127.         SimplePrincipalCollection principals = new SimplePrincipalCollection();  
  128.         principals.add(loginName, super.getName());  
  129.         super.clearCachedAuthenticationInfo(principals);  
  130.     }  
  131.       
  132.     @PostConstruct  
  133.     public void initCredentialsMatcher() {  
  134.         //该句作用是重写shiro的密码验证,让shiro用我自己的验证-->指向重写的CustomCredentialsMatcher  
  135.         setCredentialsMatcher(new CustomCredentialsMatcher());  
  136.   
  137.     }  
  138. }  
6.自定义shiroUser

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.business.shiro;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Set;  
  5.   
  6. /** 
  7.  * @description:自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息 
  8.  * @author:zhanghao 
  9.  * @date:2017/5/9 
  10.  */  
  11. public class ShiroUser implements Serializable {  
  12.     private static final long serialVersionUID = -1373760761780840081L;  
  13.       
  14.     private Long id;  
  15.     private final String loginName;  
  16.     private String name;  
  17.     private Set<String> urlSet;  
  18.     private Set<String> roles;  
  19.   
  20.     public ShiroUser(String loginName) {  
  21.         this.loginName = loginName;  
  22.     }  
  23.   
  24.     public ShiroUser(Long id, String loginName, String name, Set<String> urlSet) {  
  25.         this.id = id;  
  26.         this.loginName = loginName;  
  27.         this.name = name;  
  28.         this.urlSet = urlSet;  
  29.     }  
  30.   
  31.     public Long getId() {  
  32.         return id;  
  33.     }  
  34.   
  35.     public void setId(Long id) {  
  36.         this.id = id;  
  37.     }  
  38.   
  39.     public String getName() {  
  40.         return name;  
  41.     }  
  42.   
  43.     public void setName(String name) {  
  44.         this.name = name;  
  45.     }  
  46.   
  47.     public Set<String> getUrlSet() {  
  48.         return urlSet;  
  49.     }  
  50.   
  51.     public void setUrlSet(Set<String> urlSet) {  
  52.         this.urlSet = urlSet;  
  53.     }  
  54.   
  55.     public Set<String> getRoles() {  
  56.         return roles;  
  57.     }  
  58.   
  59.     public void setRoles(Set<String> roles) {  
  60.         this.roles = roles;  
  61.     }  
  62.   
  63.     public String getLoginName() {  
  64.         return loginName;  
  65.     }  
  66.   
  67.     /** 
  68.      * 本函数输出将作为默认的<shiro:principal/>输出. 
  69.      */  
  70.     @Override  
  71.     public String toString() {  
  72.         return loginName;  
  73.     }  
  74. }  
7.两个缓存类

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.business.shiro.cache;  
  2.   
  3. import java.util.Collection;  
  4. import java.util.Collections;  
  5. import java.util.Set;  
  6.   
  7. import org.apache.log4j.Logger;  
  8. import org.apache.shiro.cache.CacheException;  
  9. import org.springframework.cache.Cache;  
  10. import org.springframework.cache.Cache.ValueWrapper;  
  11.   
  12. /** 
  13.  * 使用spring-cache作为shiro缓存 
  14.  * @author L.cm 
  15.  * 
  16.  */  
  17. @SuppressWarnings("unchecked")  
  18. public class ShiroSpringCache<K, V> implements org.apache.shiro.cache.Cache<K, V> {  
  19.     private static final Logger logger = Logger.getLogger(ShiroSpringCache.class);  
  20.       
  21.     private final org.springframework.cache.Cache cache;  
  22.       
  23.     public ShiroSpringCache(Cache cache) {  
  24.         if (cache == null) {  
  25.             throw new IllegalArgumentException("Cache argument cannot be null.");  
  26.         }  
  27.         this.cache = cache;  
  28.     }  
  29.   
  30.     @Override  
  31.     public V get(K key) throws CacheException {  
  32.         if (logger.isTraceEnabled()) {  
  33.             logger.trace("Getting object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());  
  34.         }  
  35.         ValueWrapper valueWrapper = cache.get(key);  
  36.         if (valueWrapper == null) {  
  37.             if (logger.isTraceEnabled()) {  
  38.                 logger.trace("Element for [" + key + "] is null.");  
  39.             }  
  40.             return null;  
  41.         }  
  42.         return (V) valueWrapper.get();  
  43.     }  
  44.   
  45.     @Override  
  46.     public V put(K key, V value) throws CacheException {  
  47.         if (logger.isTraceEnabled()) {  
  48.             logger.trace("Putting object in cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());  
  49.         }  
  50.         V previous = get(key);  
  51.         cache.put(key, value);  
  52.         return previous;  
  53.     }  
  54.   
  55.     @Override  
  56.     public V remove(K key) throws CacheException {  
  57.         if (logger.isTraceEnabled()) {  
  58.             logger.trace("Removing object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());  
  59.         }  
  60.         V previous = get(key);  
  61.         cache.evict(key);  
  62.         return previous;  
  63.     }  
  64.   
  65.     @Override  
  66.     public void clear() throws CacheException {  
  67.         if (logger.isTraceEnabled()) {  
  68.             logger.trace("Clearing all objects from cache [" + this.cache.getName() + "]");  
  69.         }  
  70.         cache.clear();  
  71.     }  
  72.   
  73.     @Override  
  74.     public int size() {  
  75.         return 0;  
  76.     }  
  77.   
  78.     @Override  
  79.     public Set<K> keys() {  
  80.         return Collections.emptySet();  
  81.     }  
  82.   
  83.     @Override  
  84.     public Collection<V> values() {  
  85.         return Collections.emptySet();  
  86.     }  
  87.   
  88.     @Override  
  89.     public String toString() {  
  90.         return "ShiroSpringCache [" + this.cache.getName() + "]";  
  91.     }  
  92. }  
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.business.shiro.cache;  
  2.   
  3. import org.apache.log4j.Logger;  
  4. import org.apache.shiro.cache.Cache;  
  5. import org.apache.shiro.cache.CacheException;  
  6. import org.apache.shiro.cache.CacheManager;  
  7. import org.apache.shiro.util.Destroyable;  
  8.   
  9. /** 
  10.  * 使用spring-cache作为shiro缓存 
  11.  * 缓存管理器 
  12.  * @author L.cm 
  13.  * 
  14.  */  
  15. public class ShiroSpringCacheManager implements CacheManager, Destroyable {  
  16.     private static final Logger logger = Logger.getLogger(ShiroSpringCacheManager.class);  
  17.     private org.springframework.cache.CacheManager cacheManager;  
  18.       
  19.     public org.springframework.cache.CacheManager getCacheManager() {  
  20.         return cacheManager;  
  21.     }  
  22.   
  23.     public void setCacheManager(org.springframework.cache.CacheManager cacheManager) {  
  24.         this.cacheManager = cacheManager;  
  25.     }  
  26.   
  27.     @Override  
  28.     public <K, V> Cache<K, V> getCache(String name) throws CacheException {  
  29.         if (logger.isTraceEnabled()) {  
  30.             logger.trace("Acquiring ShiroSpringCache instance named [" + name + "]");  
  31.         }  
  32.         org.springframework.cache.Cache cache = cacheManager.getCache(name);  
  33.         return new ShiroSpringCache<K, V>(cache);  
  34.     }  
  35.   
  36.     @Override  
  37.     public void destroy() throws Exception {  
  38.         cacheManager = null;  
  39.     }  
  40.   
  41. }  
8.spring-shiro.xml

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"   
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  5.     http://www.springframework.org/schema/beans/spring-beans.xsd"  
  6.     default-lazy-init="true">  
  7.   
  8.     <description>Shiro安全配置</description>  
  9.   
  10.   
  11.     <!--安全管理器-->  
  12.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  13.         <!--设置自定义Realm-->  
  14.         <property name="realm" ref="shiroDbRealm"/>  
  15.         <!--将缓存管理器,交给安全管理器-->  
  16.         <property name="cacheManager" ref="shiroSpringCacheManager"/>  
  17.         <!-- 记住密码管理 -->  
  18.         <property name="rememberMeManager" ref="rememberMeManager"/>  
  19.         <property name="sessionManager" ref="sessionManager"/>  
  20.     </bean>  
  21.   
  22.     <!-- 項目自定义的Realm -->  
  23.     <bean id="shiroDbRealm" class="com.business.shiro.ShiroDbRealm">  
  24.         <constructor-arg index="0" name="cacheManager" ref="shiroSpringCacheManager"/>  
  25.         <constructor-arg index="1" name="matcher" ref="credentialsMatcher"/>  
  26.         <!-- 启用身份验证缓存,即缓存AuthenticationInfo信息,默认false -->  
  27.         <property name="authenticationCachingEnabled" value="true"/>  
  28.         <!-- 缓存AuthenticationInfo信息的缓存名称 -->  
  29.         <property name="authenticationCacheName" value="authenticationCache"/>  
  30.         <!-- 缓存AuthorizationInfo信息的缓存名称 -->  
  31.         <property name="authorizationCacheName" value="authorizationCache"/>  
  32.     </bean>  
  33.   
  34.     <!-- 记住密码Cookie -->  
  35.     <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">    
  36.         <constructor-arg value="rememberMe"/>  
  37.         <property name="httpOnly" value="true"/>  
  38.         <!-- 7天,采用spring el计算方便修改[细节决定成败]! -->  
  39.         <property name="maxAge" value="#{7 * 24 * 60 * 60}"/>  
  40.     </bean>  
  41.   
  42.     <!-- rememberMe管理器  -->  
  43.     <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">  
  44.         <property name="cookie" ref="rememberMeCookie"/>    
  45.     </bean>  
  46.   
  47.     <!-- Shiro Filter -->  
  48.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  49.         <!-- 安全管理器 -->  
  50.         <property name="securityManager" ref="securityManager"/>  
  51.         <!-- 默认的登陆访问url -->  
  52.         <property name="loginUrl" value="/login"/>  
  53.         <!-- 登陆成功后跳转的url -->  
  54.         <property name="successUrl" value="/menu/index"/>  
  55.         <!-- 没有权限跳转的url -->  
  56.         <property name="unauthorizedUrl" value="/login"/>  
  57.         <property name="filterChainDefinitions">  
  58.             <value>  
  59.                 <!--   
  60.                     anon  不需要认证  
  61.                     authc 需要认证  
  62.                     user  验证通过或RememberMe登录的都可以  
  63.                 -->  
  64.                 /login = anon  
  65.                 /favicon.ico = anon  
  66.                 /static/** = anon  
  67.                 /** = user  
  68.             </value>  
  69.         </property>  
  70.     </bean>  
  71.   
  72.     <!-- 用户授权信息Cache, 采用spring-cache, 具体请查看spring-ehcache.xml、spring-redis.xml -->  
  73.     <bean id="shiroSpringCacheManager" class="com.business.shiro.cache.ShiroSpringCacheManager">  
  74.         <property name="cacheManager" ref="cacheManager"/>  
  75.     </bean>  
  76.       
  77.     <!-- 会话管理器 -->  
  78.     <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
  79.         <!-- 设置全局会话超时时间 半小时 -->  
  80.         <property name="globalSessionTimeout" value="#{30 * 60 * 1000}"/>  
  81.         <!-- url上带sessionId 默认为true -->  
  82. <!--         <property name="sessionIdUrlRewritingEnabled" value="false"/> -->  
  83.         <property name="sessionDAO" ref="sessionDAO"/>  
  84.     </bean>  
  85.       
  86.     <!-- 会话DAO 用于会话的CRUD -->  
  87.     <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">  
  88.         <!-- Session缓存名字,默认就是shiro-activeSessionCache -->  
  89.         <property name="activeSessionsCacheName" value="activeSessionCache"/>  
  90.         <property name="cacheManager" ref="shiroSpringCacheManager"/>  
  91.     </bean>  
  92.       
  93.     <!-- 在方法中 注入  securityManager ,进行代理控制 -->  
  94.     <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
  95.         <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>  
  96.         <property name="arguments" ref="securityManager"/>  
  97.     </bean>  
  98.       
  99.     <!-- 自定义验证 -->  
  100.     <bean id="credentialsMatcher" class="com.business.shiro.CustomCredentialsMatcher"></bean>  
  101.       
  102. </beans>  
9.如果要再controller层中加入注解判断,还需在spring-mvc-servlet.xml中加入

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <!-- 启用shrio 控制器授权注解拦截方式 -->  
  2. <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
  3.     <property name="securityManager" ref="securityManager"/>  
  4. </bean>  
  5. <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
  6. <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  
  7. <!-- AOP式方法级权限检查  -->  
  8. <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"  
  9.       depends-on="lifecycleBeanPostProcessor">  
  10.       <property name="proxyTargetClass" value="true"/>  
  11. </bean>  
10.缓存的两个xml文件ehcache.xml,spring-ehcache.xml

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <ehcache updateCheck="false" dynamicConfig="false">  
  3.     <diskStore path="java.io.tmpdir"/>  
  4.       
  5.    <cache name="authorizationCache"  
  6.            maxEntriesLocalHeap="2000"  
  7.            eternal="false"  
  8.            timeToIdleSeconds="1800"  
  9.            timeToLiveSeconds="1800"  
  10.            overflowToDisk="false"  
  11.            statistics="true">  
  12.     </cache>  
  13.   
  14.     <cache name="authenticationCache"  
  15.            maxEntriesLocalHeap="2000"  
  16.            eternal="false"  
  17.            timeToIdleSeconds="1800"  
  18.            timeToLiveSeconds="1800"  
  19.            overflowToDisk="false"  
  20.            statistics="true">  
  21.     </cache>  
  22.       
  23.     <cache name="activeSessionCache"  
  24.            maxEntriesLocalHeap="2000"  
  25.            eternal="false"  
  26.            timeToIdleSeconds="1800"  
  27.            timeToLiveSeconds="1800"  
  28.            overflowToDisk="false"  
  29.            statistics="true">  
  30.     </cache>  
  31.       
  32.     <!-- 缓存半小时 -->  
  33.     <cache name="halfHour"   
  34.         maxElementsInMemory="10000"  
  35.         maxElementsOnDisk="100000"   
  36.         eternal="false"   
  37.         timeToIdleSeconds="1800"  
  38.         timeToLiveSeconds="1800"   
  39.         overflowToDisk="false"   
  40.         diskPersistent="false" />  
  41.           
  42.     <!-- 缓存一小时 -->  
  43.     <cache name="hour"   
  44.         maxElementsInMemory="10000"  
  45.         maxElementsOnDisk="100000"   
  46.         eternal="false"   
  47.         timeToIdleSeconds="3600"  
  48.         timeToLiveSeconds="3600"   
  49.         overflowToDisk="false"   
  50.         diskPersistent="false" />  
  51.       
  52.     <!-- 缓存一天 -->  
  53.     <cache name="oneDay"   
  54.         maxElementsInMemory="10000"  
  55.         maxElementsOnDisk="100000"   
  56.         eternal="false"   
  57.         timeToIdleSeconds="86400"  
  58.         timeToLiveSeconds="86400"   
  59.         overflowToDisk="false"   
  60.         diskPersistent="false" />  
  61.       
  62.     <!--  
  63.         name:缓存名称。  
  64.         maxElementsInMemory:缓存最大个数。  
  65.         eternal:对象是否永久有效,一但设置了,timeout将不起作用。  
  66.         timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。  
  67.         timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。  
  68.         overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。  
  69.         diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。  
  70.         maxElementsOnDisk:硬盘最大缓存个数。  
  71.         diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.  
  72.         diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。     
  73.         memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。  
  74.         clearOnFlush:内存数量最大时是否清除。  
  75.     -->  
  76.     <defaultCache name="defaultCache"  
  77.         maxElementsInMemory="10000"  
  78.         eternal="false"  
  79.         timeToIdleSeconds="120"  
  80.         timeToLiveSeconds="120"  
  81.         overflowToDisk="false"  
  82.         maxElementsOnDisk="100000"  
  83.         diskPersistent="false"  
  84.         diskExpiryThreadIntervalSeconds="120"  
  85.         memoryStoreEvictionPolicy="LRU"/>  
  86.           
  87. </ehcache>  
[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:cache="http://www.springframework.org/schema/cache"  
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.        http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.        http://www.springframework.org/schema/cache  
  8.        http://www.springframework.org/schema/cache/spring-cache.xsd">  
  9.     <!-- Spring提供的基于的Ehcache实现的缓存管理器 -->  
  10.       
  11.     <!-- 如果有多个ehcacheManager要在bean加上p:shared="true" -->  
  12.     <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
  13.         <property name="configLocation" value="classpath:spring/ehcache.xml"/>  
  14.     </bean>  
  15.       
  16.     <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">  
  17.         <property name="cacheManager" ref="ehcacheManager"/>  
  18.         <property name="transactionAware" value="true"/>  
  19.     </bean>  
  20.       
  21.     <!-- cache注解,和spring-redis.xml中的只能使用一个 -->  
  22.     <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>  
  23. </beans>  
11.applicationContext.xml导入配置文件

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <import resource="classpath:spring/spring-shiro.xml" />  
  2. <import resource="classpath:spring/spring-ehcache.xml" />  
12.LoginController控制层方法

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.business.controller.system;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import javax.annotation.Resource;  
  6.   
  7. import org.apache.commons.lang3.StringUtils;  
  8. import org.apache.shiro.SecurityUtils;  
  9. import org.apache.shiro.authc.DisabledAccountException;  
  10. import org.apache.shiro.authc.IncorrectCredentialsException;  
  11. import org.apache.shiro.authc.UnknownAccountException;  
  12. import org.apache.shiro.authc.UsernamePasswordToken;  
  13. import org.apache.shiro.subject.Subject;  
  14. import org.springframework.stereotype.Controller;  
  15. import org.springframework.web.bind.annotation.RequestMapping;  
  16. import org.springframework.web.bind.annotation.RequestMethod;  
  17. import org.springframework.web.bind.annotation.RequestParam;  
  18. import org.springframework.web.servlet.mvc.support.RedirectAttributes;  
  19.   
  20. import com.business.controller.BaseController;  
  21. import com.business.service.sysService.UserService;  
  22. import com.business.util.SessionUtil;  
  23. import com.google.common.collect.Maps;  
  24.   
  25. @Controller  
  26. public class LoginController extends BaseController {  
  27.   
  28.     @Resource  
  29.     private UserService userService;  
  30.       
  31.     @RequestMapping(value = "/login",method=RequestMethod.GET)  
  32.     public String login() {  
  33.         return "login";  
  34.     }  
  35.   
  36.     @RequestMapping(value = "/login",method=RequestMethod.POST)  
  37.     public String login(RedirectAttributes attributes, String username, String password, @RequestParam(value = "online", defaultValue = "0") Integer rememberMe) {  
  38.           
  39.         Map<String, Object> map = Maps.newHashMap();  
  40.         if (StringUtils.isBlank(username)) {  
  41.             map.put("errorInfo""用户名不能为空");  
  42.         }  
  43.         if (StringUtils.isBlank(password)) {  
  44.             map.put("errorInfo""密码不能为空");  
  45.         }  
  46.         Subject user = SecurityUtils.getSubject();  
  47.         UsernamePasswordToken token = new UsernamePasswordToken(username, username+password);  
  48.         // 设置记住密码  
  49.         token.setRememberMe(1 == rememberMe);  
  50.         try {  
  51.             user.login(token);  
  52.             return "redirect:/menu/index";  
  53.         } catch (UnknownAccountException e) {  
  54.             map.put("errorInfo""账号不存在!");  
  55.             attributes.addFlashAttribute("error", map);  
  56.             return "redirect:/login";  
  57.         } catch (DisabledAccountException e) {  
  58.             map.put("errorInfo""账号未启用!");  
  59.             attributes.addFlashAttribute("error", map);  
  60.             return "redirect:/login";  
  61.         } catch (IncorrectCredentialsException e) {  
  62.             map.put("errorInfo""密码错误!");  
  63.             attributes.addFlashAttribute("error", map);  
  64.             return "redirect:/login";  
  65.         } catch (Throwable e) {  
  66.             map.put("errorInfo""登录异常!");  
  67.             attributes.addFlashAttribute("error", map);  
  68.             return "redirect:/login";  
  69.         }  
  70.     }  
  71.       
  72.     @RequestMapping(value = "/logout")  
  73.     public String logout() {  
  74.         SessionUtil.removeSession();  
  75.         Subject subject = SecurityUtils.getSubject();  
  76.         subject.logout();  
  77.         return "redirect:/login";  
  78.     }  
  79. }  
12.如何在控制层使用注解,可以在baseController中加入总的异常处理

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @ExceptionHandler    
  2.    public String exception(HttpServletRequest request, Exception e) {    
  3.        //对异常进行判断做相应的处理    
  4.        if(e instanceof AuthorizationException){    
  5.            return "redirect:/logout";    
  6.        }  
  7.        return null;  
  8. }  
0 0