shiro--认证部分
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 入门程序代码
// 用户登陆和退出
@Test
public void testLoginAndLogout() { // 创建securityManager工厂,通过ini配置文件创建securityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory(
"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", "111111"); 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
package cn.itcast.shiro.realm; import java.util.ArrayList;
import java.util.List; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.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
* @version 1.0
*/
public class CustomRealm extends AuthorizingRealm { // 设置realm的名称
@Override
public void setName(String name) {
super.setName("customRealm");
} // 用于认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException { // token是用户输入的
// 第一步从token中取出身份信息
String userCode = (String) token.getPrincipal(); // 第二步:根据用户输入的userCode从数据库查询
// .... // 如果查询不到返回null
//数据库中用户账号是zhangsansan
/*if(!userCode.equals("zhangsansan")){//
return null;
}*/ // 模拟从数据库查询到密码
String password = "111111"; // 如果查询到返回认证信息AuthenticationInfo SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
userCode, password, this.getName()); return simpleAuthenticationInfo;
} // 用于授权
@Override
protected AuthorizationInfo 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 = new SimpleAuthorizationInfo();
//将上边查询到授权信息填充到simpleAuthorizationInfo对象中
simpleAuthorizationInfo.addStringPermissions(permissions); return simpleAuthorizationInfo;
} }
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中配置凭证匹配器
shiro--认证部分的更多相关文章
- Apache Shiro 使用手册(二)Shiro 认证
认证就是验证用户身份的过程.在认证过程中,用户需要提交实体信息(Principals)和凭据信息(Credentials)以检验用户是否合法.最常见的"实体/凭证"组合便是&quo ...
- Apache Shiro 认证过程
3.1.1 示例 Shiro验证Subjects 的过程中,可以分解成三个不同的步骤: 1. 收集Subjects 提交的Principals(身份)和Credentials(凭证): 2. 提 ...
- shiro认证登录实现
准备工作: 在web.xml中配置shiro核心过滤器 在spring配置文件中提供核心过滤器运行所需要的辅助bean对象,在对象内注入安全管理器 拦截认证 配置三个url 拦截除了登录页面以及认证a ...
- 【shiro】(4)---Shiro认证、授权案例讲解
Shiro认证.授权案例讲解 一.认证 1. 认证流程 2.用户密码已经加密.加盐的用户认证 (1)测试类 // 用户登陆和退出,这里我自定了一个realm(开发肯定需要自定义realm获取 ...
- 无状态shiro认证组件(禁用默认session)
准备内容 简单的shiro无状态认证 无状态认证拦截器 import com.hjzgg.stateless.shiroSimpleWeb.Constants; import com.hjzgg.st ...
- 转:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法、shiro认证与shiro授权
原文地址:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法.shiro认证与shiro授权 以下是部分内容,具体见原文. shiro介绍 什么是shiro shiro是Apache ...
- frame shiro 认证示例及原理简述
shiro 认证流程 1.创建一个 javaSE 的maven项目(quickstart),并添加依赖 <dependency> <groupId>junit</grou ...
- Shiro认证的另一种方式
今天在学习shiro的时候使用另一种shiro验证的方式. 总体的思路是: (1)先在自己的方法中进行身份的验证以及给出提示信息.(前提是将自己的验证方法设为匿名可访问) (2)当验证成功之后到Shi ...
- 将 Shiro 作为应用的权限基础 二:shiro 认证
认证就是验证用户身份的过程.在认证过程中,用户需要提交实体信息(Principals)和凭据信息(Credentials)以检验用户是否合法.最常见的“实体/凭证”组合便是“用户名/密码”组合. 一. ...
- springmvc+shiro认证框架配置
1,在web.xml中配置fiter,如下所示 <!-- shiro的filter --> <!-- shiro过虑器,DelegatingFilterProxy通过代理模式将spr ...
随机推荐
- (贪心 map) Flying to the Mars hdu1800
Flying to the Mars Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- 新建体(3):dbms_job下新建一个job定期自动执行存储过程
http://blog.csdn.net/thinkscape/article/details/7411012http://java-admin.iteye.com/blog/231159sql窗口执 ...
- 关于串session
关于session: 最近在用IE浏览器调试不同用户所拥有的权限功能,出现了串session.串session,主要的流程结构如下: 解决方法: 在IE快捷方式上点击鼠标右键>属性>快捷方 ...
- Go-day07
今日内容概要: 1.json解析 2.文件操作 3.命令行参数 4.错误处理 一.Golang里的类型断言 1 em必须为initerface类型才可以进行类型断言 比如如下代码会报错 s := &q ...
- jquery 实现按回车键登录功能的写法
<script> //登录的逻辑函数 自己写 function submitFuc(){ var loginName= $("#loginName").val(); v ...
- rancher2.0部署
1.安装前准备 #当前环境介绍 操作系统:CentOS7.3 硬件:2C 4G内存 官网要求Docker版本: 1.12.6 1.13.1 17.03.2 #关闭防火墙 systemctl stop ...
- JMETER压力测试报错:JAVA.NET.BINDEXCEPTION: ADDRESS ALREADY IN USE: CONNECT
最近在实现接口压力测试的时候遇到这样的一个问题 当线程数持续上升到一个点的时候,运行脚本的时候有很多报错,如图: java.net.BindException: Address already in ...
- hdu 6380
#include<bits/stdc++.h> #define in(a) scanf("%d",&a) using namespace std; struct ...
- 剑指offer面试题4: 二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- [Android] Android ViewPager 中加载 Fragment的两种方式 方式(二)
接上文: https://www.cnblogs.com/wukong1688/p/10693338.html Android ViewPager 中加载 Fragmenet的两种方式 方式(一) 二 ...