1.1
什么是
shiro

shiro

apache
的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。

spring
中有
spring security (
原名
Acegi)
,是一个权限框架,它和
spring
依赖过于紧密,没有
shiro
使用简单。

shiro
不依赖于
spring

shiro
不仅可以实现
web
应用的权限管理,还可以实现
c/s
系统,分布式系统权限管理,
shiro
属于轻量框架,越来越多企业项目开始使用
shiro

使用
shiro
实现系统 的权限管理,有效提高开发效率,从而降低开发成本。

1.2
shiro
架构

subject
:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。

securityManager
:安全管理器,主体进行认证和授权都 是通过
securityManager
进行。

authenticator
:认证器,主体进行认证最终通过
authenticator
进行的。

authorizer
:授权器,主体进行授权最终通过
authorizer
进行的。

sessionManager

web
应用中一般是用
web
容器对
session
进行管理,
shiro
也提供一套
session
管理的方式。

SessionDao
:  通过
SessionDao
管理
session
数据,针对个性化的
session
数据存储需要使用
sessionDao

cache Manager
:缓存管理器,主要对
session
和授权数据进行缓存,比如将授权数据通过
cacheManager
进行缓存管理,和
ehcache
整合对缓存数据进行管理。

realm
:域,领域,相当于数据源,通过
realm
存取认证、授权相关数据。

注意:在
realm
中存储授权和认证的逻辑。

cryptography

密码管理,提供了一套加密
/
解密的组件,方便开发。比如提供常用的散列、加
/
解密等功能。

比如
md5散列算法。

1.3
jar

与其它
java
开源框架类似,将
shiro

jar
包加入项目就可以使用
shiro
提供的功能了。
shiro-core
是核心包必须选用,还提供了与
web
整合的
shiro-web


spring
整合的
shiro-spring
、与任务调度
quartz
整合的
shiro-quartz
等,下边是
shiro

jar
包的
maven
坐标。

<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-quartz</artifactId>
            <version>1.2.3</version>
        </dependency>

也可以通过引入shiro-all包括shiro所有的包:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.3</version>
</dependency>


参考lib目录 :

1
shiro
认证

1.1
shiro
认证流程

1.2
shiro
入门程序工程 环境

jar
包:
shiro-core.jar

工程结构:

1.3
shiro
认证入门程序

1.3.1
shiro-first.ini

通过此配置文件创建
securityManager
工厂。

需要修改
eclipse

ini
的编辑器
:

配置数据:

1.1.1
入门程序代码

//用户登陆和退出
@Testpublic voidtestLoginAndLogout() {//创建securityManager工厂,通过ini配置文件创建securityManager工厂
        Factory<SecurityManager> factory = newIniSecurityManagerFactory("classpath:shiro-first.ini");//创建SecurityManager
        SecurityManager securityManager =factory.getInstance();//将securityManager设置当前的运行环境中
SecurityUtils.setSecurityManager(securityManager);//从SecurityUtils里边创建一个subject
        Subject subject =SecurityUtils.getSubject();//在认证提交前准备token(令牌)
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "666666666666");try{//执行认证提交
subject.login(token);
}
catch(AuthenticationException e) {//TODO Auto-generated catch block e.printStackTrace();
}
//是否认证通过 boolean isAuthenticated =subject.isAuthenticated();

System.out.println(
"是否认证通过:" +isAuthenticated);//退出操作 subject.logout();//是否认证通过 isAuthenticated =subject.isAuthenticated();

System.out.println(
"是否认证通过:" +isAuthenticated);



}

1.1.1
执行流程

1
、通过
ini
配置文件创建
securityManager

2
、调用
subject.login
方法主体提交认证,提交的
token

3

securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证。

4

ModularRealmAuthenticator调用IniRealm(

realm
传入
token)

ini
配置文件中查询用户信息

5

IniRealm
根据输入的
token

UsernamePasswordToken
)从
shiro-first.ini
查询用户信息,根据账号查询用户信息(账号和密码)

如果查询到用户信息,就给ModularRealmAuthenticator返回用户信息(账号和密码)

如果查询不到,就给ModularRealmAuthenticator
返回
null

6

ModularRealmAuthenticator接收IniRealm返回Authentication
认证信息

如果返回的认证信息是
null

ModularRealmAuthenticator抛出异常(
org.apache.shiro.authc.UnknownAccountException

如果返回的认证信息不是
null
(说明
inirealm
找到了用户),对
IniRealm
返回用户密码
(在
ini
文件中存在)和
token
中的密码 进行对比,如果不一致抛出异常(
org.apache.shiro.authc.IncorrectCredentialsException

个人解释一下上面说的:
securityManager最终由ModularRealmAuthenticator进行认证 《== 为什么是它认证

Ctrl+ T
查看
Authenticator
接口的超类型 层次结构。如下:

上图中会跑到
AuthenticatingSecurityManager
认证实现类,类里面有个属性
是由
ModularRealmAuthenticator创建的,

用接口authenticator
来引用

1.1.2
小结:

ModularRealmAuthenticator
作用进行认证,需要调用
realm
查询用户信息(在数据库中存在用户信息)

ModularRealmAuthenticator进
行密码对比
(认证过程)。

realm
:需要根据
token
中的身份信息去查询数据库(入门程序使用
ini
配置文件),如果查到用户返回认证信息,如果查询不到返回
null

1.1
自定义
realm

将来实际开发需要
realm
从数据库中查询用户信息。

1.1.1
realm
接口

1.1.1
自定义
realm

packagecn.itcast.shiro.realm;importjava.util.ArrayList;importjava.util.List;importorg.apache.shiro.authc.AuthenticationException;importorg.apache.shiro.authc.AuthenticationInfo;importorg.apache.shiro.authc.AuthenticationToken;importorg.apache.shiro.authc.SimpleAuthenticationInfo;importorg.apache.shiro.authz.AuthorizationInfo;importorg.apache.shiro.authz.SimpleAuthorizationInfo;importorg.apache.shiro.realm.AuthorizingRealm;importorg.apache.shiro.subject.PrincipalCollection;/*** 
* <p>
* Title: CustomRealm
* </p>
* <p>
* Description:自定义realm
* </p>
* <p>
* Company: www.itcast.com
* </p>
*
*
@author传智.燕青
* @date 2015-3-23下午4:54:47
*
@version1.0*/ public class CustomRealm extendsAuthorizingRealm {//设置realm的名称 @Overridepublic voidsetName(String name) {super.setName("customRealm");
}
//用于认证 @OverrideprotectedAuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token)
throwsAuthenticationException {//token是用户输入的//第一步从token中取出身份信息 String userCode =(String) token.getPrincipal();//第二步:根据用户输入的userCode从数据库查询//....//如果查询不到返回null//数据库中用户账号是zhangsansan /*if(!userCode.equals("zhangsansan")){//
return null;
}
*/ //模拟从数据库查询到密码 String password = "666666666666";//如果查询到返回认证信息AuthenticationInfo SimpleAuthenticationInfo simpleAuthenticationInfo= newSimpleAuthenticationInfo(
userCode, password,
this.getName());returnsimpleAuthenticationInfo;
}
//用于授权 @OverrideprotectedAuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//从 principals获取主身份信息//将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型), String userCode =(String) principals.getPrimaryPrincipal();//根据身份信息获取权限信息//连接数据库...//模拟从数据库获取到数据 List<String> permissions = new ArrayList<String>();
permissions.add(
"user:create");//用户的创建 permissions.add("items:add");//商品添加权限//....//查到权限数据,返回授权信息(要包括 上边的permissions) SimpleAuthorizationInfo simpleAuthorizationInfo = newSimpleAuthorizationInfo();//将上边查询到授权信息填充到simpleAuthorizationInfo对象中 simpleAuthorizationInfo.addStringPermissions(permissions);returnsimpleAuthorizationInfo;
}

}

1.1.1
配置
realm

需要在
shiro-realm.ini
配置
realm
注入到
securityManager
中。

1.1.2
测试

同上边的入门程序,需要更改
ini
配置文件路径:

Factory<SecurityManager> factory =
new
IniSecurityManagerFactory("classpath:shiro-realm.ini");

1.1
散列算法

通常需要对密码
进行散列,常用的有
md5

sha


md5
密码,如果知道散列后的值可以通过穷举算法,得到
md5
密码对应的明文。

建议对
md5
进行散列时加
salt
(盐),进行加密相当 于对原始密码
+
盐进行散列。

正常使用时散列方法:

在程序中对原始密码
+
盐进行散列,将散列值存储到数据库中,并且还要将盐也要存储在数据库中。

如果进行密码对比时,使用相同
方法,将原始密码
+
盐进行散列,进行比对。

1.1.1
md5
散列测试程序:

1.1.1
自定义
realm
支持散列算法

需求:实际开发时
realm
要进行
md5
值(明文散列后的值)的对比。

1.1.1.1
新建
realm(CustomRealmMd5)


realm
中配置凭证匹配器

标签: none

添加新评论