`
freeroy
  • 浏览: 74529 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

安全认证框架-Apache Shiro研究心得(转)

 
阅读更多

最近因为项目需要,研究了一下Apache Shiro安全认证框架,把心得记录下来。

(原创by:西风吹雨)

     Apache Shrio是一个安全认证框架,和Spring Security相比,在于他使用了和比较简洁易懂的认证和授权方式。其提供的native-session(即把用户认证后的授权信息保存在其自身提供Session中)机制,这样就可以和HttpSession、EJB Session Bean的基于容器的Session脱耦,到到和客户端应用、Flex应用、远程方法调用等都可以使用它来配置权限认证。 

 1、sessionMode

    在普通的WEB项目中,我们可以选择使用native session或者是HttpSession,通过设置securityManager的sessionMode参数为http或native即可。

 2、realm

    我们可以基于jdbc,ldap,text,activeDirectory,jndi等多种方式来获取用户基本信息,角色信息,权限信息等。只需要在 securityManager中指定使用相应的realm实现即可,其在这各方面都提供了对应的缺省实现,比如我们常用的基于数据库表的形式来配置用户 权限信息,就可以使用其缺省实现的jdbcRealm(org.apache.shiro.realm.jdbc.JdbcRealm)。当然,如果认证 信息来自于多方面,多个不同的来源(比如来自两个库中,或者一个数据库,一个是ldap,再配上一个缺省的基于文本的测试用等等),我们可以为 securityManager指定realms参数,即把这一组安全配置都配置上。各个具体的realm实现提供了方法来获取用户基本信息、角色、权限 等。

    realm的授权信息可以存放在Cache中,Cache的名称可以通过设置其authorizationCacheName参数指定。

3、缓存    

   目前Shrio缺省提供了基于ehCache来缓存用户认证信息和授权信息的实现。只需要配置

org.apache.shiro.web.mgt.DefaultWebSecurityManager 这个 cacheManager并设置给SecurityManager即可。如果项目中已经存在使用的ehCacheManager配置(org.springframework.cache.ehcache.EhCacheManagerFactoryBean),DefaultWebSecurityManager则可以指定使用现有的ehCacheManager,如果不指定,它将自行使用缺省配置创建一个。同时,也可以设置cacheManagerConfigFile参数来指定ehCache的配置文件。

 

下例中的shiro.authorizationCache是用来存放授权信息的Cache,我们在配置realm(如myRealm或 jdbcReaml)时,把authorizationCacheName属性设置shiro.authorizationCache来对应。

 

ehcache.xml

<ehcache>

    <diskStore path="java.io.tmpdir/tuan-oauth"/>

 


    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />

    <!-- We want eternal="true" (with no timeToIdle or timeToLive settings) because Shiro manages session
expirations explicitly.  If we set it to false and then set corresponding timeToIdle and timeToLive properties,
ehcache would evict sessions without Shiro's knowledge, which would cause many problems
(e.g. "My Shiro session timeout is 30 minutes - why isn't a session available after 2 minutes?"
Answer - ehcache expired it due to the timeToIdle property set to 120 seconds.)

diskPersistent=true since we want an enterprise session management feature - ability to use sessions after
even after a JVM restart.  -->
    <cache name="shiro-activeSessionCache"
           maxElementsInMemory="10000"
           eternal="true"
           overflowToDisk="true"
           diskPersistent="true"
           diskExpiryThreadIntervalSeconds="600"/>

    <cache name="shiro.authorizationCache"
           maxElementsInMemory="100"
           eternal="false"
           timeToLiveSeconds="600"
           overflowToDisk="false"/>

</ehcache>

 

当我们把securityManager的sessionMode参数设置为native时,那么shrio就将用户的基本认证信息保存到缺省名称为shiro-activeSessionCache 的Cache中

org.apache.shiro.web.mgt.DefaultWebSecurityManager 在sessionMode参数设置为native时,缺省使用的是DefaultWebSessionManager来管理Session,该 管理类缺省使用的是使用MemorySessionDAO基于内存来保存和操作用户基本认证信息。如果系统内的用户数特别多,我们需要使用 CacheSessionDao来基于Cache进行操作,因此,这里需要显示配置一个 sessionManager(org.apache.shiro.web.session.mgt.DefaultWebSessionManager), 并配置该sessionManager的sessionDao为 CacheSessionDao(org.apache.shiro.session.mgt.eis.CachingSessionDAO,需用其实现 类org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO)。配置CacheSessionDao时,我们可以指定属性activeSessionsCacheName的名称来替换掉缺省名 shiro-activeSessionCache。

我们再把该sessionManager配置给DefaultWebSecurityManager就可以了。

 

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/>
        <property name="sessionMode" value="native"/>
        <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->
        <property name="realm" ref="myRealm"/>
        <property name="sessionManager" ref="sessionManager"/>
    </bean>

    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="sessionDAO" ref="sessionDAO"/>
    </bean>

    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
        <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
    </bean>

 

从以上我们可以看出

   a、我们可以指定sessionManager的sessionDao,在某些情况下,我们也可以通过实现自定义的sessionDao来把用户认证信息 保存在memcache,mongodb,ldap,database中,达到和其他应用共享用户认证信息的目的,以此达到SSO的目的(当 然,sessionId得一致,这个属于我们可以在应用商定怎么设定一致的sessionId的问题)。

   b、cacheManager我们也可以自己实现一个,可以根据应用情况来考虑,比如存放在memcache中之类。

 

 

4、配置

    Web项目中,普通的web项目可以采用ini文件来对shiro进行配置。基于spring的项目可以采用和Spring集成的方式配置。

 

基于Spring集成的Web项目的基本配置文件如下:

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

    <!-- =========================================================
         Shiro Core Components - Not Spring Specific
         ========================================================= -->

    <!-- Shiro's main business-tier object for web-enabled applications
         (use DefaultSecurityManager instead when there is no web environment)-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/>
        <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->
        <property name="sessionMode" value="native"/>
        <property name="realm" ref="myRealm"/>
    </bean>

    <!-- Let's use some enterprise caching support for better performance.  You can replace this with any enterprise
         caching framework implementation that you like (Terracotta+Ehcache, Coherence, GigaSpaces, etc -->
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <!-- Set a net.sf.ehcache.CacheManager instance here if you already have one.  If not, a new one
             will be creaed with a default config:                -->
        <property name="cacheManager" ref="ehCacheManager"/>
        <!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance to inject, but you want
             a specific Ehcache configuration to be used, specify that here.  If you don't, a default
             will be used.:
        <property name="cacheManagerConfigFile" value="classpath:some/path/to/ehcache.xml"/> -->
    </bean>

    <!-- Used by the SecurityManager to access security data (users, roles, etc).
         Many other realm implementations can be used too (PropertiesRealm,
         LdapRealm, etc. -->
    <bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
        <property name="name" value="jdbcRealm"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="credentialsMatcher">
            <!-- The 'bootstrapDataPopulator' Sha256 hashes the password
                 (using the username as the salt) then base64 encodes it: -->
            <bean class="org.apache.shiro.authc.credential.Sha256CredentialsMatcher">
                <!-- true means hex encoded, false means base64 encoded -->
                <property name="storedCredentialsHexEncoded" value="false"/>
                <!-- We salt the password using the username, the most common practice: -->
                <property name="hashSalted" value="true"/>
            </bean>
        </property>
        <property name="authorizationCacheName" value="shiro.authorizationCache"/>
    </bean>

    <bean id="myRealm" class="org.apache.shiro.realm.text.IniRealm" init-method="init">
        <property name="name" value="myRealm"/>
        <property name="authorizationCacheName" value="shiro.authorizationCache"/>
        <property name="resourcePath" value="classpath:config/myRealm.ini"/>

    </bean>

    <!-- =========================================================
         Shiro Spring-specific integration
         ========================================================= -->
    <!-- Post processor that automatically invokes init() and destroy() methods
         for Spring-configured Shiro objects so you don't have to
         1) specify an init-method and destroy-method attributes for every bean
            definition and
         2) even know which Shiro objects require these methods to be
            called. -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- Enable Shiro Annotations for Spring-configured beans.  Only run after
         the lifecycleBeanProcessor has run: -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>


    <!-- Secure Spring remoting:  Ensure any Spring Remoting method invocations can be associated
         with a Subject for security checks. -->
    <bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!-- Define the Shiro Filter here (as a FactoryBean) instead of directly in web.xml -
         web.xml uses the DelegatingFilterProxy to access this bean.  This allows us
         to wire things with more control as well utilize nice Spring things such as
         PropertiesPlaceholderConfigurer and abstract beans or anything else we might need: -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/login"/>
        <property name="successUrl" value="/index"/>
        <property name="unauthorizedUrl" value="/unauthorized"/>
        <!-- The 'filters' property is not necessary since any declared javax.servlet.Filter bean
             defined will be automatically acquired and available via its beanName in chain
             definitions, but you can perform overrides or parent/child consolidated configuration
             here if you like: -->
        <!-- <property name="filters">
            <util:map>
                <entry key="aName" value-ref="someFilterPojo"/>
            </util:map>
        </property> -->
        <property name="filterChainDefinitions">
            <value>
                /login = authc
                /account = user
                /manage = user,roles[admin]
            </value>
        </property>
    </bean>

</beans>

5、基于url资源的权限管理

    我们可以简单配置在shiroFilter的filterChainDefinitions中,也可以考虑通过一个文本文件,我们读入内容后设置进去。或者通过Ini类来装入Ini文件内容,到时取出urls的部分来设置给shiroFilter的filterChainDefinitions。也可以把这部分数据存入数据库表中,到时读出一个Map来设置给shiroFilter的filterChainDefinitionsMap属性。

 

6、url的配置

   authc是认证用户(rememberMe的用户也必须再次登录才能访问该url),配置成user才能让rememberMe用户也可以访问。

 

7、rememberMe Cookie的处理

    Shiro有一套缺省机制,由CookieRememberMeManager实现。

其有一个SimpleCookie类,保存对应的用户信息等。每次保存时,系统把SimpleCookie的信息设置好之后,先用DefaultSerializer把其用jvm缺省序列化方式序列化成byte[],然后再用cipherService(缺省是aes加密算法)来加密该byte[],最后用Base64.encodeToString(serialized)压缩成一个字符串,再写入名称为rememberMe的Cookie中。

 

读取时,通过把该rememberMe Cookie的内容用byte[] decoded = Base64.decode(base64)解压出该byte[],再用cipherService解密,最后用DefaultSerializer反序列化出来该SimpleCookie类。

 

如果我们有自定义的rememberMe Cookie需要处理,特别是在和其他网站一起SSO,通过访问主域的Cookie来获取记录的用户信息时,我们需要重新实现rememberMeManager(可以考虑继承AbstractRememberMeManager), 和根据实际用的序列化方式Serializer来实现一个(比如考虑通用性,用json方式序列化)。在Spring配置中,配置好 RememberMeManager,装配上sericerlizer和cipherService(根据实际情况选用适当的加密算法),最后把 rememberMeManager设置给DefaultWebSecurityManager即可。如果非常简单的cookie,可以直接实现RememberMeManager的几个接口方法也行。

 

说到这里, Apache Shiro的一些基本配置和扩展情况应该差不多了。关于它的授权和使用等模型,其官网有基本的说明,也有相关的例子。这里主要是针对其实际应用中的一些使用和扩展方式。

 

 

原文链接:http://blog.sina.com.cn/s/blog_6638b10d0100pd88.html

分享到:
评论

相关推荐

    安全认证框架-Apache_Shiro研究心得

    ### 安全认证框架-Apache Shiro研究心得 #### Apache Shiro简介 Apache Shiro 是一个强大且易用的 Java 安全框架,提供了认证、授权、加密和会话管理功能,可以非常容易地开发出足够安全的应用——无论它们是部署...

    shiro学习心得

    Apache Shiro 是一个强大且易用的 Java 安全框架,它提供了认证(Authentication)、授权(Authorization)、加密(Cryptography)以及会话管理等功能。通过本文档,将深入探讨 Shiro 的核心概念,并结合实际应用...

    xmljava系统源码-shiro:shirow3school+自编教程

    安全框架,提供了认证、授权、加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。并且相对于其他安全框架,Shiro 要简单的多。本教程只介绍基本的 Shiro 使用,不会过多分析源码等...

    java技能总结

    **Shiro简介**:Apache Shiro 是一个强大且易用的 Java 安全框架,它提供了全面的安全解决方案,包括认证、授权、加密以及会话管理等功能。Shiro 的设计目标是使开发者能够轻松地将这些功能集成到他们的应用中。 **...

    基于springboot的经方药食两用服务平台源码数据库.doc

    Apache Shiro是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。在本项目中,Shiro被用来实现用户的权限管理和安全认证,确保了系统的安全性。 ##### 3.4 AJAX技术 AJAX(Asynchronous ...

    Java毕业设计(美食分享系统)源码.zip

    - **安全控制**:Spring Security或者Apache Shiro用于用户认证与授权。 2. **核心功能模块**: - **用户模块**:包括用户注册、登录、个人信息管理等功能,通常会涉及验证码验证、密码加密等安全措施。 - **菜...

    Java项目之基于基于SSM的美食网站(源码)

    6. **用户认证与授权**:项目可能会使用Spring Security或Apache Shiro等安全框架进行用户登录、权限控制,确保只有合法用户才能访问特定资源。 7. **模板引擎**:为了方便动态页面的生成,项目可能使用FreeMarker...

    java版关于ssh技术的班级管理系统

    - **用户认证与授权**:Spring Security或Apache Shiro可以用于实现用户登录、权限控制等功能,确保只有授权的用户才能访问特定的班级信息。 - **学生信息管理**:Hibernate可以用来存储和管理每个班级的学生信息,...

    基于Springboot的学生读书笔记共享系统源码数据库.zip

    - 使用Spring Security或Apache Shiro进行用户认证和授权,确保只有合法用户才能访问特定资源,保护学生的个人信息和笔记内容。 6. **笔记上传与下载**: - 系统应支持笔记的上传功能,可能需要处理文件存储问题...

    Java项目实战-基于Javaee的影视创作论坛的设计与实现(附源码,部署说明).zip

    了解Spring Security或Apache Shiro等安全框架的应用,能为论坛提供更安全的保障。 10. **性能优化**: 项目可能涉及缓存策略、负载均衡、性能监控等方面,学习如何使用如Redis、Nginx等工具进行优化,提高系统的...

    学生资源管理系统

    Java的安全框架如Spring Security或Apache Shiro可用于实现用户认证和授权,保护敏感信息不被未经授权的访问。同时,系统还需要考虑到数据备份和恢复策略,以防止数据丢失。 总的来说,学生资源管理系统是一个综合...

    博客与项目管理系统

    同时,安全是Web应用的重要一环,Java Web应用通常会使用Spring Security或Apache Shiro等库来处理用户认证和授权,防止未授权访问。 开发这样的系统需要掌握前后端分离的概念,理解MVC(Model-View-Controller)...

    JavaWeb及数据库综合设计报告书.doc

    这些问题需要通过学习和实践来解决,例如使用CORS解决跨域,使用乐观锁或悲观锁处理并发,使用Spring Security或Apache Shiro增强安全性,使用MyBatis Plus进行性能优化。 6. **心得体会**: 在完成课程设计的过程...

    基于ssm+jsp的在线日语培训平台.zip

    - 安全性:防止SQL注入、XSS攻击等,采用Spring Security或Apache Shiro进行权限控制。 - 性能优化:如使用缓存技术减轻数据库压力,通过负载均衡提升系统并发能力。 - 测试:进行单元测试、集成测试,确保每个功能...

    BLOG一个个人网站

    安全方面,Spring Security或Apache Shiro可以用于权限管理和认证。它们提供了基础的身份验证和授权功能,确保只有合法用户才能访问特定资源。此外,为了防止SQL注入和XSS攻击,还需要对用户输入进行验证和过滤。 ...

    基于Javaee的影视创作论坛的设计与实现.zip

    在用户认证和权限控制上,可能会采用Spring Security或Apache Shiro等安全框架,确保只有合法用户才能访问特定资源,同时实现角色权限的划分,如管理员、普通用户等,保障论坛的正常运营。 此外,考虑到论坛的高...

    基于ssm的颜墨插画交流网站的设计与实现【附源码】

    4. **安全机制**:Spring Security或Shiro可实现用户认证与授权,防止未授权访问和XSS、CSRF等攻击。 二、功能模块详解 1. **用户管理**:用户可以进行注册、登录,密码加密存储,确保用户信息安全。支持找回密码...

    基于java的美食网站的设计与实现(1)2.zip

    7. **安全与身份验证**:Spring Security或Apache Shiro可能被用来实现用户登录注册、权限控制等功能,确保网站的安全性。 8. **单元测试与集成测试**:JUnit和Mockito等工具可用于编写测试用例,确保代码质量和...

Global site tag (gtag.js) - Google Analytics