大纲
Shiro简介及架构图讲解
ini配置文件讲解
Shiro搭建及简单认证实现
加密及凭证匹配器
Spring整合Shiro完成登录功能.
知识点详解
一、Shiro简介
1.Shiro一个Java权限框架.
1.1在项目中把涉及到权限的业务提出来用shiro完成.
2.Shiro架构图
2.1 Subject 主体.对应一个用户,用户所有的信息都存放在Subject中.无论什么编程语言只要有Subject都可以使用Shiro框架.
2.2 Cryptography: Shiro密码管理功能.
2.2.1 密码加密,加盐,迭代等等.
2.3 Security Manager: 权限管理器.Shiro核心内容.所有Shiro功能都封装到Security Manager
2.4 Authenticator: 认证器. 例如登录注册等功能就属性认证功能.
2.5 Authorizer:授权器. 例如:判断用户是否具有某个角色,判断用户是否有某个权限,判断用户可以访问的菜单.
2.6 Session Manager : Session管理器.使用Shiro后,shiro会禁用HttpSession,使用Shiiro自己的Session管理器.
2.7 Cache Manager : 缓存管理. 支持Cookie的缓存(remember me),支持Redis的缓存.
2.8 Realm: 域.作用是当Shiro希望访问数据库时,通过Realm组件完成的.
二、Shiro.ini文件
1.ini (InitializationFile) 初始文件.Window系统文件扩展名.
2.Shiro 使用时可以连接数据库,也可以不连接数据库.
2.1 如果不连接数据库,可以在shiro.ini中配置静态数据.
3. Shiro.ini文件组成部分
3.1[main] :定义全局变量
3.1.1 内置securityManager对象.
3.1.2 操作内置对象时,在[main]里面写东西\
[main] securityManager.属性=值
myobj=com.bjsxt.lei securityManager.对象属性=$myobj |
3.2[users] :定义用户名和密码
[users] # 定义用户名为zhangsan 密码为zs zhangsan=zs # 定义用户名lisi密码为lisi同时具有role1和role2两个角色 lisi=lisi,role1,role2 |
3.3[roles]: 定义角色
[roles] role1=权限名1,权限名2 role2=权限3,权限4 |
3.4[urls] : 定义哪些内置urls生效.在web应用时使用.
[urls] url地址=内置filter或自定义filter # 访问时出现/login的url必须去认证.支持authc对应的Filter /login=authc # 任意的url都不需要进行认证等功能. /** = anon # 所有的内容都必须保证用户已经登录. /**=user # url abc 访问时必须保证用户具有role1和role2角色. /abc=roles[“role1,role2”] |
三、Shiro 环境搭建实现认证
认证流程
实现步骤
2.1 在pom.xml中导入jar
<dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency> <!-- <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> --> </dependencies> |
2.2 在src /java/resources下新建shiro.ini文件
[users] zhangsan=zs |
2.3 编写代码,实现认证
// SecurityManager JDK也有这个类,在java.lang包 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager sm = factory.getInstance(); // 只要线程不变,Subject不变 SecurityUtils.setSecurityManager(sm); Subject subject = SecurityUtils.getSubject(); // Subject subject = (new Subject.Builder()).buildSubject(); // 客户端传递过来的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "zs"); try { subject.login(token); System.out.println("登录成功"); } catch (UnknownAccountException e) { System.out.println("账户不存在"); } catch (IncorrectCredentialsException e) { System.out.println("密码错误"); } |
四、实现授权
1.流程图
2.常用api
2.1 subject.hasRole(“”); 判断是否有角色
2.2 subject.hashRoles(List);分别判断用户是否具有List中每个内容
2.3 subject.hasAllRoles(Collection);返回boolean,要求参数中所有角色用户都需要具有.
2.4 subject.isPermitted(“”);判断是否具有权限.
五、自定义Realm
1. Principal:身份
1.1 用户名可以是身份
1.2 邮箱可以是身份.
1.3 手机可以是身份.
1.4 用户对象也可以是身份.
2.Credentials:凭证.
2.1 密码可以是凭证
2.2 证书也是可以是凭证.
3. SecurityManager接口只有一个普通java类DefaultSecurityManager
4. 实现步骤:
4.1 新建类继承AuthorizingRealm
4.2 在doGetAuthenticationInfo实现认证过程.
4.3 代码
public class MyRealm extends AuthorizingRealm{
//执行授权方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // TODO Auto-generated method stub return null; } //执行认证 //当subject.login()时自动调用该方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { Object obj = token.getPrincipal(); System.out.println("principal:"+obj); Object obj2 = token.getCredentials(); new String((char[])obj2); System.out.println("credentials:"+new String((char[])obj2));
//如果方法返回值为null,shiro认为用户名不存在. //如果返回值不是null,判断AuthenticationInfo中凭证和subject.login时凭证是否匹配 //第一个参数: 第一个参数写什么以后登录这个用户的身份就是什么. //第二个参数是从数据库中取出的凭证信息,判断这个信息和subject.login()第二个参数是否匹配. //第三个参数:都是用户主键值. SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(obj, "zs", "myrealm"); return info; }
} |
4.4 在shiro.ini中配置自定义Realm
[main] myrealm=com.bjsxt.realm.MyRealm
securityManager.realms=$myrealm |
4.5 执行subject.login()调用doGetAuthenticationInfo
六. 凭证匹配器
1. 保证数据库中密码是加密的密码
2.在shiro.ini中配置凭证匹配器
[main] myrealm=com.bjsxt.realm.MyRealm # 定义凭证匹配器类 credentialsMatcher =org.apache.shiro.authc.credential.HashedCredentialsMatcher # 设置加密算法 credentialsMatcher.hashAlgorithmName=md5 # 迭代次数 credentialsMatcher.hashIterations=2 # 引用凭证匹配器 myrealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$myrealm |
3.在自定义realm中
3.1 第三个参数:加盐值. 类型是ByteSource类型,bytes()跟字符串类型,不能使用Long
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),rs.getObject("password"), ByteSource.Util.bytes(rs.getObject("id").toString()) ,"key:"+rs.getObject("id")); |
七、自定义Realm中-doGetAuthorizationInfo()
1.该方法被执行情况
- java中hasRole() , isPermitted();
- 使用注解
@RequiresRoles("role1") @RequiresPermissions("") |
2.在jsp中标签
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<shiro:hasRole name="role1"> abc </shiro:hasRole> <shiro:hasPermission name="quanxian"> jqk </shiro:hasPermission>
|