shiro使用教程

 

一、shiro是什么

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。不仅可以在Web项目中使用,在普通的项目中也是可以使用的

 

二、shiro可以做什么

shiro可以进行细粒度地权限控制,包括对方法,对链接,对页面显示进行权限控制。

 

三、在Web项目中使用shiro进行权限管理

1、  在web.xml中添加shiro的拦截器

    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <async-supported>true</async-supported>
        <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>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

 

2、  spring-mvc.xml中添加shiro的权限注解支持

<aop:config proxy-target-class="true"></aop:config>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
         <property name="securityManager" ref="securityManager"/>
</bean>

 

3、  使用spring对ehcache进行缓存管理

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    <!-- 支持缓存注解 -->
    <cache:annotation-driven cache-manager="ehcacheManager" />
 
    <!--ehcache-->
    <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="classpath:ehcache.xml"/>
    </bean>
 
    <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="cacheManagerFactory"/>
    </bean>
</beans>

  

 

4、  使用ehcache进行缓存管理

在ehcache中添加如下缓存块

    <diskStore path="java.io.tmpdir"/>
    <cache name="authorizationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>
 
    <cache name="authenticationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="shiro-activeSessionCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

 

5、实现CacheManager的接口,对shiro权限使用spring进行缓存管理

public class SpringCacheManagerWrapper implements CacheManager {
    private org.springframework.cache.CacheManager cacheManager;

    /**
     * 设置spring cache manager
     *
     * @param cacheManager
     */
    public void setCacheManager(org.springframework.cache.CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }
 
    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
        org.springframework.cache.Cache springCache = cacheManager.getCache(name);
        return new SpringCacheWrapper(springCache);
    }

    static class SpringCacheWrapper implements Cache {
        private org.springframework.cache.Cache springCache;
        SpringCacheWrapper(org.springframework.cache.Cache springCache) {
            this.springCache = springCache;
        }

        @Override
        public Object get(Object key) throws CacheException {
            Object value = springCache.get(key);
            if (value instanceof SimpleValueWrapper) {
                return ((SimpleValueWrapper) value).get();
            }
            return value;
        }

        @Override
        public Object put(Object key, Object value) throws CacheException {
            springCache.put(key, value);
            return value;
        }
 
        @Override
        public Object remove(Object key) throws CacheException {
            springCache.evict(key);
            return null;
        }

        @Override
        public void clear() throws CacheException {
            springCache.clear();
        }
 
        @Override
        public int size() {
            if(springCache.getNativeCache() instanceof Ehcache) {
                Ehcache ehcache = (Ehcache) springCache.getNativeCache();
                return ehcache.getSize();
            }

            throw new UnsupportedOperationException("invoke spring cache abstract size method not supported");
        }
 
        @Override
        public Set keys() {
            if(springCache.getNativeCache() instanceof Ehcache) {
                Ehcache ehcache = (Ehcache) springCache.getNativeCache();
                return new HashSet(ehcache.getKeys());
            }
            throw new UnsupportedOperationException("invoke spring cache abstract keys method not supported");
        }
 
        @Override
        public Collection values() {
            if(springCache.getNativeCache() instanceof Ehcache) {
                Ehcache ehcache = (Ehcache) springCache.getNativeCache();
                List keys = ehcache.getKeys();
                if (!CollectionUtils.isEmpty(keys)) {
                    List values = new ArrayList(keys.size());
                    for (Object key : keys) {
                        Object value = get(key);
                        if (value != null) {
                            values.add(value);
                        }
                    }
                    return Collections.unmodifiableList(values);
                } else {
                    return Collections.emptyList();
                }
            }
            throw new UnsupportedOperationException("invoke spring cache abstract values method not supported");
        }
    }
}

 

6、自定义放在session中的实体

public class CustomPrincipal implements Serializable {
    private Integer id;
    private String username;

    public CustomPrincipal(String username) {
        this.username = username;
    }
 
    public CustomPrincipal(int id, String username) {
        this.id = id;
        this.username = username;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
 
    /**
     * 本函数输出将作为默认的<shiro:principal/>输出.
     */
    @Override
    public String toString() {
        return username;
    }
} 

 

7、重写realm

public class AdministratorRealm extends AuthorizingRealm {
    private AdministratorService administratorService;
    public AdministratorService getAdministratorService() {
        return administratorService;
    }
 
    public void setAdministratorService(AdministratorService administratorService) {
        this.administratorService = administratorService;
    } 

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        CustomPrincipal customPrincipal = (CustomPrincipal)principals.getPrimaryPrincipal();
        String username = customPrincipal.getUsername();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        Set<String> roles = administratorService.getRoles(username);
        roles.add(UserConstants.ADMINISTRATOR_STR);
        authorizationInfo.setRoles(roles); 
        authorizationInfo.setStringPermissions(administratorService.getPermissions(username));
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = (String)usernamePasswordToken.getPrincipal();
        Administrator administrator = administratorService.getAdministrator(username);
        if (administrator == null) {
            throw new UnknownAccountException();//没找到帐号
        }
 
        if (Boolean.FALSE.equals(administrator.getAdmiStatus())) {
            throw new LockedAccountException(); //帐号锁定
        } 
        CustomPrincipal principal = new CustomPrincipal(administrator.getAdmiId(), administrator.getAdmiAccount());
        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                principal, //用户名
                administrator.getAdmiPassword(), //密码
                ByteSource.Util.bytes(administrator.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }
 
    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }
 
    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }
 
    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }
}

  

8、spring-shiro.xml实例化类

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

       <aop:config proxy-target-class="true"></aop:config>

       <!-- 缓存管理器 -->
       <bean id="cacheManager" class="com.misuosi.mshop.shiro.cache.SpringCacheManagerWrapper">
              <property name="cacheManager" ref="ehcacheManager"/>
       </bean>

       <!-- 凭证匹配器 -->
       <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
              <property name="hashAlgorithmName" value="md5"/>
              <property name="hashIterations" value="2"/>
              <property name="storedCredentialsHexEncoded" value="true"/>
       </bean>

       <!-- Realm实现 -->
       <bean id="administratorRealm" class="com.misuosi.mshop.shiro.realm.AdministratorRealm">
              <property name="administratorService" ref="administratorService"/>
              <property name="credentialsMatcher" ref="credentialsMatcher"/>
              <property name="cachingEnabled" value="false"/>
              <property name="authenticationCachingEnabled" value="true"/>
              <property name="authenticationCacheName" value="authenticationCache"/>
              <property name="authorizationCachingEnabled" value="true"/>
              <property name="authorizationCacheName" value="authorizationCache"/>
       </bean>
 
       <!-- 会话ID生成器 -->
       <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>

       <!-- 会话Cookie模板 -->
       <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
              <constructor-arg value="sid"/>
              <property name="httpOnly" value="true"/>
              <property name="maxAge" value="-1"/>
       </bean>
 
       <!-- 会话DAO -->
       <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
              <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
              <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
       </bean>
 
       <!-- 会话验证调度器 -->
       <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
              <property name="sessionValidationInterval" value="1800000"/>
              <property name="sessionManager" ref="sessionManager"/>
       </bean>
 
       <!-- 会话管理器 -->
       <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
              <property name="globalSessionTimeout" value="1800000"/>
              <property name="deleteInvalidSessions" value="true"/>
              <property name="sessionValidationSchedulerEnabled" value="true"/>
              <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
              <property name="sessionDAO" ref="sessionDAO"/>
              <property name="sessionIdCookieEnabled" value="true"/>
              <property name="sessionIdCookie" ref="sessionIdCookie"/>
       </bean>

       <!-- 安全管理器 -->
       <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
              <property name="realm" ref="administratorRealm"/>
              <property name="sessionManager" ref="sessionManager"/>
              <property name="cacheManager" ref="cacheManager"/>
       </bean>

       <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
       <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
              <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
              <property name="arguments" ref="securityManager"/>
       </bean>
 
       <!-- 基于Form表单的身份验证过滤器 -->
       <bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
              <property name="successUrl" value="/admin/index"/>
              <property name="loginUrl" value="/admin/login"/>
       </bean>
 
       <bean id="adminLogoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
              <property name="redirectUrl" value="/admin/login"/>
       </bean>
 
       <!-- Shiro的Web过滤器 -->
       <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
              <property name="securityManager" ref="securityManager"/>
              <property name="filters">
                     <util:map>
                            <entry key="adminAuthc" value-ref="formAuthenticationFilter"/>
                            <entry key="adminLogout" value-ref="adminLogoutFilter"/>
                     </util:map>
              </property>
              <property name="filterChainDefinitions">
                     <value>
                            /admin/login = adminAuthc
                            /admin/logout = adminLogout
                            /admin/** = adminAuthc,roles[admin]
                     </value>
              </property>
       </bean>
 
       <!-- Shiro生命周期处理器-->
       <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>  

 

9、freemarker使用shiro的标签

把标签的实现贴到freemarker.tag的包中,在freemarker的配置中添加freemarker标签。

public class ShiroTagFreeMarkerConfigurer extends FreeMarkerConfigurer {
    @Override
    public void afterPropertiesSet() throws IOException, TemplateException {
        super.afterPropertiesSet();
        this.getConfiguration().setSharedVariable("shiro", new ShiroTags());
    }
}

 

10、完成

 

posted @ 2015-07-13 15:43  ICE_XUE  阅读(4069)  评论(0编辑  收藏  举报