shiro安全框架.docx

上传人:b****0 文档编号:9334058 上传时间:2023-05-18 格式:DOCX 页数:21 大小:147.99KB
下载 相关 举报
shiro安全框架.docx_第1页
第1页 / 共21页
shiro安全框架.docx_第2页
第2页 / 共21页
shiro安全框架.docx_第3页
第3页 / 共21页
shiro安全框架.docx_第4页
第4页 / 共21页
shiro安全框架.docx_第5页
第5页 / 共21页
shiro安全框架.docx_第6页
第6页 / 共21页
shiro安全框架.docx_第7页
第7页 / 共21页
shiro安全框架.docx_第8页
第8页 / 共21页
shiro安全框架.docx_第9页
第9页 / 共21页
shiro安全框架.docx_第10页
第10页 / 共21页
shiro安全框架.docx_第11页
第11页 / 共21页
shiro安全框架.docx_第12页
第12页 / 共21页
shiro安全框架.docx_第13页
第13页 / 共21页
shiro安全框架.docx_第14页
第14页 / 共21页
shiro安全框架.docx_第15页
第15页 / 共21页
shiro安全框架.docx_第16页
第16页 / 共21页
shiro安全框架.docx_第17页
第17页 / 共21页
shiro安全框架.docx_第18页
第18页 / 共21页
shiro安全框架.docx_第19页
第19页 / 共21页
shiro安全框架.docx_第20页
第20页 / 共21页
亲,该文档总共21页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

shiro安全框架.docx

《shiro安全框架.docx》由会员分享,可在线阅读,更多相关《shiro安全框架.docx(21页珍藏版)》请在冰点文库上搜索。

shiro安全框架.docx

shiro安全框架

Shiro是JAVA世界中新近出现的权限框架,较之JAAS和SpringSecurity,Shiro在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势。

本文就带领读者一睹Shiro的风采。

可能大家早先会见过J-security,这个是Shiro的前身。

在2009年3月初之前,这个安全框架叫做J-security,由于某些原因,更名为Shiro(或者Ki,意为Fortress),是Apache的孵化项目,鉴于本文编写时Shiro的还没有正式发布的版本,本文使用的是Jsecurity的稳定版本0.9,本文中Shiro等同于Jsecurity。

本文将涉及Shiro的整体框架、安全模型、关键概念类,同时给出了Shiro以及GrailsShiroPlugin的使用示例,可以下载文中使用的源代码。

本文代码的开发环境:

∙Jsecurity0.9

∙Grails1.2.0

∙GrailsShiroPlugin1.0.1

∙SpringSourceToolSuite2.3

Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。

如下是它所具有的特点:

1.易于理解的JavaSecurityAPI;

2.简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory等);

3.对角色的简单的签权(访问控制),支持细粒度的签权;

4.支持一级缓存,以提升应用程序的性能;

5.内置的基于POJO企业会话管理,适用于Web以及非Web的环境;

6.异构客户端会话访问;

7.非常简单的加密API;

8.不跟任何的框架或者容器捆绑,可以独立运行。

目前还有其他出现较早的安全框架,比如JAAS,SpringSecurity。

JAAS—面世的时间最早,但是鉴于其在使用上有很大的限制,很少有人真正的使用它。

可以说它不是一个好的应用程序级别的安全框架;

SpringSecurity—目前是Java安全框架领域当之无愧的老大,已经非常成熟了;如果使用Spring框架,可以首选SpringSecurity,但是对于单应用来说,Shiro更显简单方便。

下面就开始我们的Shiro之旅吧!

首先,我们来看看的Shiro的整体架构,见下图:

图1.整体架构

从上图可以看出,Shiro主要有四个组件:

1.SecurityManager

典型的Facade,Shiro通过它对外提供安全管理的各种服务。

2.Authenticator

对“Whoareyou?

”进行核实。

通常涉及用户名和密码。

这个组件负责收集principals和credentials,并将它们提交给应用系统。

如果提交的credentials跟应用系统中提供的credentials吻合,就能够继续访问,否则需要重新提交principals和credentials,或者直接终止访问。

3.Authorizer

身份份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“whocandowhat”,或者“whocandowhichactions”。

Shiro采用“基于Realm”的方法,即用户(又称Subject)、用户组、角色和permission的聚合体。

4.SessionManager

这个组件保证了异构客户端的访问,配置简单。

它是基于POJO/J2SE的,不跟任何的客户端或者协议绑定。

Shiro的认证和签权可以通过JDBC、LDAP或者ActiveDirectory来访问数据库、目录服务器或者ActiveDirectory中的人员以及认证/签权信息。

SessionManager通过会话DAO可以将会话保存在cache中,或者固化到数据库或文件系统中。

从Shiro的框架图,已经能够体会到这个工具的简单了。

下面让我们来看看Shiro是如何工作的。

先了解一下它的安全模型吧!

见下图:

图2.安全模型

上图中,涉及了Shiro的五个概念:

∙Subject是安全领域术语,除了代表人,它还可以是应用。

在单应用中,可将其视为User的同义词。

∙Principal是Subject的标识,一般情况下是唯一标识,比如用户名。

∙Role和Permission分别代表了不同粒度的权限,从上图中可以看出Role的粒度更大些,Permission代表了系统的原子权限,比如数据的修改、删除权限。

对于简单的权限应用,可以不需要Permission。

∙Realm是一个执行者,负责真正的认证和鉴权。

实现应用的安全模块的关键在于:

定义合适的role和permission,这就需要遵循如下原则:

1.role没有实质内容,只是代表一组permission,目的是为了管理的方便,一般都是动态定义;

2.permission一般都是预先定义好的,不允许动态改变,除非源代码改动,它才会变化,它是整个安全模块的基础;

3.要使permission也能动态定义,并非不可能,但是这将使鉴权非常复杂,甚至可能导致鉴权语句遍布整个程序,得不偿失;

4.当然有一个例外:

如果知道permission动态定义的规则和鉴权规则,如Grails的fileter中“${controllerName}:

${actionName}:

${params.id}”也可实现permission的动态定义

理解Shiro的架构和安全模型了,我们来看看更具体些的内容。

下图显示了Shiro中的关键概念类(参考资料--JSecurityMiniGuide)。

图3.关键类

AuthenticationToken和AuthenticationInfo

前者在认证前使用,描述认证所需的信息,最常用的就是username和password对;后者在认证后使用,内容同前,但是表示已经经过认证的信息。

RememberMe

代表的是一种可能状态,并不表示该Subject已经经过了认证。

对于一些普通的操作,这种可能状态并无大碍,但一旦涉及安全敏感的操作,必须经过认证。

Credentials和CredentialsMatcher

Credentials是Subject的证书,在认证时使用,最常用的就是password。

在通常情况下,为了安全起见,Subject的credentials都需要加密保存,于是CredentialsMatcher的作用就体现出来了,见下图:

图4.CredentialsMatcher的作用

这里CredentialsMatcher需要将加密后的证书跟用户登录时提供的证书进行比对,完成认证的过程。

PAM=PluggableAuthenticationModules

在有多个Realm的时候使用。

由认证策略决定认证结果,即PAM=Relams+认证策略。

一般的策略有3种:

AllSuccessful、AtLeastOneSuccessful和FirstSuccessful。

AuthorizationInfo

可以看成是Role+Permission的组合体。

PermissionResolver和Permission

它们之间的关系如下:

图5.PermissionResolver和Permission的关系

在Shiro中,权限被转化为一种字符串描述(字符串分级表示,称之为WildcardPermission),从而将权限转化为类似于对象equals的操作(Shiro中的implies方法)。

内置的权限有2个:

∙AllPermission,总是返回true

∙WildcardPermission,权限字符串的表示方式。

这里重点声明一下。

WildcardPermission是Shiro的精妙之处,我们可以将权限表示成字符串,这样对权限的控制可以不拘泥于物理存储,比如对messagge类具有修改和删除权限可以标识为:

message:

update,delete:

*,其中‘*’表示所有;第一级分隔符为‘:

’;第二级分隔符为‘,’,而对于权限字符串的解释完全可以由应用自己来定。

如果要比较权限字符串,可以使用permission1.implies(permission2),它分别比较对应位置的字符串,在如下情况中,结果会返回true:

∙permission1中的子串有*或permission1子串==permission2子串;

∙permission1无子串,permission2有;

∙permission1有子串,permission2无,permission1的所有子串都是*。

总的说来,Shiro中的Permission需要注意如下内容:

1.权限的比较实际是字符串的比较,只不过是考虑到了字符串的分级

2.字符串的分级划分完全由使用者自己决定,Shiro的惯例是3级:

资源:

操作:

实例。

3.字符串的使用必须一致,分隔符之间不要有空格,避免无意间引入的不一致。

如:

定义使用“file:

create,update:

1”,而验证使用“file:

update”,那么分解之后一个是“update”,一个是“update”,因空格而引起不等。

Realm

这是一个实际访问安全实体的组件,一般是应用相关的,跟数据源的关系是1-1。

它负责完成认证和鉴权,getAuthenticationInfo代表了login的尝试,鉴权方法则由Authorizer继承而来。

此处也体现了Shiro代码的另一个特点,通过继承来扩充功能。

以常用的JdbcRealm为例,其继承链如下:

图6.JdbcRealm的继承链

Session

它关联一个Subject的上下文,其作用类似于在HttpSession中保存用户标识,session一旦过期,则重新登录。

Shiro的Session是独立的,其目的是做到环境无关性。

为了利用Web环境中,Shiro实现了一个直接使用HttpSession的WebSession。

SecurityManager

这是一个Façade接口,=Authenticator+Authorizer+SessionFactory。

在整体框架图中已经看到了它在Shiro中所处的位置。

其特点同Realm,一样是使用继承不断地扩充功能。

对于Web应用一般使用DefaultWebSecurityManager。

Filter

在Web环境下使用filter进行认证和权限检查是毋庸置疑的,而Shiro的特点则在于由一个主Filter将一群子filter串起来:

图7.Filter的作用

在实际使用时,须注意:

1.web.xml中只需配置JSecurityFilter。

对于Spring应用,则使用SpringJSecurityFilter;

2.子filter作为主filter的配置参数值出现,特点是:

顺序相关

a. 

▪对于多个URL,验证顺序是由上至下,类似Exception的匹配。

因此,使用顺序应该是由细到粗。

▪对于同一URL,子filter的验证顺序是从左至右的AND操作。

3.如果配置值中含有分隔符,如Permission,就需要使用引号来转义。

Subject

subject代表了一个用户的状态和操作,它提供了所有安全相关的操作,包括认证和签权。

可以将其视为另一种形式的Façade。

缺省实现是将这些操作委派给其内部包含的SecurityManager。

Configuration

configuration负责将所有这些组件串起来,最终创建SecurityManager。

在Shiro中,缺省格式是ini。

整个配置关系如下图:

图8.配置关系

其中:

∙JSecurityFilter创建Configuration实例,并将ini参数值传给Configuation。

在Spring环境中,分别使用SpringJSecurityFilter和SpringIniWebConfiguration。

∙Configuration实际就是SecurityManager的Factroy,对SpringIniWebConfiguration而言,它需要知道SecurityManager的BeanName,该值由SpringJSecurityFilter的初始化参数“securityManagerBeanName”值决定。

即SpringJSecurityFilter,实际有两个初始化参数:

∙ 

oconfig,是ini配置文件内容

osecurityManagerBeanName,是SecurityManager的BeanName

SecurityUtils

这是Shiro中最重要的工具类,由它可以方便地获得Subject和SecurityManager。

杂项

∙AOP,提供AOP方面的支持,实现对某个类某个方法的拦截,从而使权限控制延伸至类的方法。

∙Cache,提供缓存支持

∙Codec,提供编码方面的支持

∙Crypto,提供加密支持

∙IO,从多个资源位置读写原始数据

∙JNDI,提供jndi支持

∙util,工具类支持

∙标签类,用于Web页面

对Shiro有了一个感官认识后,下面我们就亲自动手试试这个框架吧!

下面给大家举了两个使用案例。

在开始案例的学习之前,先作好准备工作--获得Shiro相关的jar包,获取途径有两种:

1.直接到J-security的网站上下载,本文用到的就是这个;

2.由于Shiro目前是Apache的孵化项目,还没有发布正式的版本,但是我们可以到Subversion上下载代码,之后使用Maven构建

mkdirshiro

cdshiro

svncohttps:

//svn.apache.org/repos/asf/incubator/shiro/trunk/

mvninstall

之后会得到shiro-all-1.0-incubating-SNAPSHOT.jar,就可以使用Shiro了。

示例一:

让Shiro为你的应用服务

这个案例中,我们使用Grails向大家讲述Shiro的使用。

我们要实现如下功能:

1.用户登录后方可进入系统;

2.假定一个message的安全内容,用户可以创建message的内容,但是如果需要修改/删除message的内容就必须具有相应的权限;

3.Admin具有所有的权限;

4.message的权限跟角色关联。

示例程序执行的流程如下:

图9程序执行的流程

从上图中可以看到,任何人要访问应用中受保护的URL,首先要通过Filter检查用户是否经过认证;对于没有认证的用户会将访问定向到登录页面;对于已经认证的用户,会对用户进行鉴权,这个用户是否具有访问其所提交的URL的权限;而管理员可以给角色授权。

好了,开始程序的编写啦!

创建安全领域类

最常见的就是User、Role和Permission,见清单1。

清单1.User/Role/Permission的Domainclass

classUser{

Stringusername

Stringpassword

statichasMany=[roles:

Role]

staticbelongsTo=Role

……

}

classRole{

Stringrolename

statichasMany=[users:

User,permissions:

Permission]

……

}

classPermission{

Stringpermission

statichasMany=[roles:

Role]

staticbelongsTo=Role

……

}

 

这里使用了最简单的情形,即权限传递结构为:

Permission->Role->User。

通常情况下,Permission也可以分配给单个User。

创建一个安全实体

实体名为message,见清单2。

只有经过授权的用户才能对这个实体进行修改和删除。

清单2.message的Domainclass

classMessage{

Stringdetails

Useruser

staticconstraints={

}

}

 

配置web.xml

清单3.在web.xml加入SecurityFilter的内容:

SecurityFilter

org.jsecurity.spring.SpringJSecurityFilter

securityManagerBeanName

jsecSecurityManager

SecurityFilter

/*

 

这里需要注意:

∙这个Filter应该在Grails的web.xml中所有缺省的Filter最后;

∙url-pattern不要使用“/**”,因为这样会造成登录页的css和图片无法访问。

解决办法,可以通过遵循“只能通过Controller/Action访问”这个规则,并使用Grails的Filter机制,可以保证所有安全URL不被非法访问。

创建realm

清单4.conf/spring/resources.groovy

beans={

credentialMatcher(

org.jsecurity.authc.credential.Sha1CredentialsMatcher){

storedCredentialsHexEncoded=true

}

permissionResolver(

org.jsecurity.authz.permission.WildcardPermissionResolver)

realm(org.jsecurity.realm.jdbc.JdbcRealm){

permissionResolver=ref("permissionResolver")

dataSource=ref("dataSource")

permissionsLookupEnabled=true

permissionsQuery="selectpermissionfrom

permission,role_permissions,rolewhere

permission.id=permission_idandrole_id=role.idandrolename=?

"

userRolesQuery="selectrolenamefromrole,role_users,user

whererole.id=role_idanduser_id=user.idandusername=?

"

authenticationQuery="selectpasswordfromuserwhereusername=?

"

}

jsecSecurityManager(

org.jsecurity.web.DefaultWebSecurityManager){

bean->bean.destroyMethod="destroy"

realms=[ref("realm")]

}

}

 

这里使用了JdbcRealm,同时根据应用情况修改了相应的SQL。

如果允许Permission直

接分配给User,即Permission和User之间是多对多关系,那么permissionsQuery应该使用union,即“role相关permissionunionuser相关permission”。

对于User有多个Role的情况,JdbcRealm会循环得出总的结果。

安全守护神:

SecurityFilters

下面就是我们的安全守护神:

SecurityFilters,这里遵循Grails的Filter语法。

见清单5。

清单5.SecurityFilters

importorg.jsecurity.SecurityUtils

classSecurityFilters{

deffilters={

authc(controller:

'*',action:

'*',){

before={

if(controllerName!

='auth'){

defsubject=SecurityUtils.subject

if(!

subject.authenticated){

redirect(

controller:

'auth',

action:

'login',

params:

[

targetUri:

request.forwardURI-request.contextPath

])

returnfalse

}

}

}

}

admin(controller:

'user|role|permission',action:

'*'){

before={

defsubject=SecurityUtils.subject

if(!

subject.hasRole('admin')){

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 育儿知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2