您的位置:首页 > 其它

Shiro入门学习一

2017-10-10 22:02 447 查看

Shiro入门学习一

Shiro官网

推荐教程:

跟我学Shiro

shiro介绍以及推荐视频教程

Apache Shiro是Java的一个安全框架。Shiro可以帮助我们完成:认证、授权、加密、会话管理、与Web集成、缓存等



Authentication
-身份认证/登录

Authorization
-授权,即权限验证,验证某个已认证的用户是否拥有某个权限

首先,我们从外部来看Shiro吧,即从应用程序角度的来观察如何使用Shiro完成工作。如下图:



可以看到:应用代码直接交互的对象是
Subject
,也就是说Shiro的对外API核心就是
Subject
;其每个API的含义:

Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是
Subject
,如网络爬虫,机器人等;即一个抽象概念;所有
Subject
都绑定到
SecurityManager
,与
Subject
的所有交互都会委托给
SecurityManager
;可以把
Subject
认为是一个门面;
SecurityManager
才是实际的执行者;

SecurityManager:安全管理器;即所有与安全有关的操作都会与
SecurityManager
交互;且它管理着所有
Subject
;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成
DispatcherServlet
前端控制器;

Realm:域,Shiro从从
Realm
获取安全数据(如用户、角色、权限),就是说
SecurityManager
要验证用户身份,那么它需要从
Realm
获取相应的用户进行比较以确定用户身份是否合法;也需要从
Realm
得到用户相应的角色/权限进行验证用户是否能进行操作;可以把
Realm
看成DataSource,即安全数据源。

也就是说对于我们而言,最简单的一个Shiro应用:

1、应用代码通过
Subject
来进行认证和授权,而
Subject
又委托给
SecurityManager


2、我们需要给
Shiro
SecurityManager
注入
Realm
,从而让
SecurityManager
能得到合法的用户及其权限进行判断。

Shiro HelloWorld

使用
Maven
创建项目,在
pom.xml
导入shiro的包,log4j的包,如下的
pom.xml


<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.0</version>
</dependency>

</dependencies>


在项目的
src/main/resources
下,创建log4j的配置文件和一个
shiro.ini
文件,项目结构如下:



shiro.ini
中配置2个用户,内容如下:

[users]
wz=123456
jack=123


此处使用
ini
配置文件,通过
[users]
指定了两个主体:
wz=123456
jack=123


HelloWorld.java
测试文件的内容如下,具体的步骤见注释,如下:

package com.wz.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;

public class HelloWorld {

public static void main(String[] args) {
//读取配置文件
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//获取SecurityManager实例
SecurityManager securityManager = factory.getInstance();
//绑定给SecurityUtils
SecurityUtils.setSecurityManager(securityManager);
//得到当前执行的用户
Subject currentUser = SecurityUtils.getSubject();
//创建token令牌
UsernamePasswordToken token = new UsernamePasswordToken("wz", "123456");
try {
//身份验证
currentUser.login(token);
System.out.println("身份认证成功");
} catch (AuthenticationException e) {
e.printStackTrace();
System.out.println("身份认证失败");
}
//退出
currentUser.logout();
System.out.println("logout");

}

}


测试运行,控制台会输出
身份认证成功


上面的例子大致演示了一个身份认证的过程。

身份验证,即在应用中谁能证明他就是他本人。一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明。

在shiro中,用户需要提供principals (身份)和credentials(证明)给shiro,从而应用能验证用户身份:

principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/邮件/手机号。

credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书等。

最常见的principalscredentials组合就是用户名/密码了。

详细的说明可参考教程第二章 身份验证——《跟我学Shiro》

从如上代码可总结出身份验证的步骤

1.收集用户身份/凭证,即如用户名/密码;

2.调用
Subject.login
进行登录,如果失败将得到相应的
AuthenticationException
异常,根据异常提示用户错误信息;否则登录成功;

3.最后调用
Subject.logout
进行退出操作。

身份认证流程



流程如下:

1.首先调用
Subject.login(token)
进行登录,其会自动委托给Security Manager,调用之前必须通过
SecurityUtils.setSecurityManager()
设置;

2.SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;

3.Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实现;

4.Authenticator可能会委托给相应的
AuthenticationStrategy
进行多Realm身份验证,默认
ModularRealmAuthenticator
会调用
AuthenticationStrategy
进行多Realm身份验证;

5.Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。

Realm

Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。如我们之前的ini配置方式将使用
org.apache.shiro.realm.text.IniRealm


Shiro默认提供的Realm



以后一般继承AuthorizingRealm(授权)即可;其继承了AuthenticatingRealm(即身份验证),而且也间接继承了CachingRealm(带有缓存实现)。其中主要默认实现如下:

org.apache.shiro.realm.text.IniRealm
[users]
部分指定用户名/密码及其角色;
[roles]
部分指定角色即权限信息;

org.apache.shiro.realm.text.PropertiesRealm
user.username=password,role1,role2
指定用户名/密码及其角色;
role.role1=permission1,permission2
指定角色及权限信息;

org.apache.shiro.realm.jdbc.JdbcRealm:通过sql查询相应的信息,如“
select password from users where username = ?
”获取用户密码,“
select password, password_salt from users where username = ?
”获取用户密码及盐;“
select role_name from user_roles where username = ?
”获取用户角色;“
select permission from roles_permissions where role_name = ?
”获取角色对应的权限信息;也可以调用相应的api进行自定义sql;

JDBC Realm使用

参考【一头扎进Shiro】视频教程第二讲

先创建数据库
shiro
,创建一个
users


CREATE DATABASE /*!32312 IF NOT EXISTS*/`db_shiro` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `shiro`;

/*Table structure for table `users` */

DROP TABLE IF EXISTS `users`;

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(20) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

/*Data for the table `users` */

insert  into `users`(`id`,`userName`,`password`) values (1,'wz','123');


创建一个
jdbc_realm.ini
文件,内容如下,设置数据源和realm

[main]
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/shiro
dataSource.user=root
dataSource.password=""
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm


注意,我这里密码为空,需设置为
dataSource.password=""
,需要添加上
""
,否则可能会提示错误
java.lang.IllegalArgumentException: Line argument must contain a key and a value. Only one


测试用例,与上面基本差不多,把配置文件设置为
jdbc_realm.ini
,如下:

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:jdbc_realm.ini");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shiro