Shiro入门学习一

来源:互联网 发布:家具软件管理 编辑:程序博客网 时间:2024/05/19 15:41

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、我们需要给ShiroSecurityManager注入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=123456jack=123

此处使用ini配置文件,通过[users]指定了两个主体:wz=123456jack=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.PropertiesRealmuser.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.JdbcRealmdataSource=com.mchange.v2.c3p0.ComboPooledDataSourcedataSource.driverClass=com.mysql.jdbc.DriverdataSource.jdbcUrl=jdbc:mysql://localhost:3306/shirodataSource.user=rootdataSource.password=""jdbcRealm.dataSource=$dataSourcesecurityManager.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");
原创粉丝点击