Mycat
分库分表:
mycat是一个虚拟的数据库服务器,并不充当存储数据的业务,本身自己链接的时逻辑数据库
数据真实存储在物理数据库上面
读写分离:
原理
让主数据库实现增删改业务,让从数据库实现查询的业务
数据一直想可以通过mysql的主从复制机制来保护数据同步
实现方式:
读写分离需要主从复制,使用mysql自带的主从复制功能即可
开发步骤:
§ 配置server.xml文件 需要配置,保留以前即可,如果有多个逻辑数据库,只需要在schemas里面添加即可.中间用逗号隔开.
§ 配置schema.xml文件
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!--
配置mycat的物理数据库和逻辑表
<property name = "schema">ZKL_TABLE</property>
name = "ZKL_TABLE" 两者之间保持一致
-->
<schema name = "ZKL_TABLE" checkSQLschema = "true" sqlMaxLimit = "100">
<table name = "user" dataNode = "dn01" />
<table name = "student" dataNode = "dn02" />
<table name = "dept" dataNode = "dn01,dn02" primaryKey = "d_id" autoIncrement = "true" rule = "mod-long" />
</schema>
<!--分库分表配置 分片-->
<dataNode name = "dn01" dataHost = "master" database = "ZKL_TABLE"/>
<dataNode name = "dn02" dataHost = "slave01" database = "ZKL_TABLE" />
<!--注意事项:尽量schema配置放在一起,dataNode配置放在一起-->
<!--配置物理数据库 真实的数据库-->
<dataHost name = "master" maxCon = "1000" minCon = "10" balance = "1" writeType = "0" dbType = "mysql" dbDriver = "native">
<!--配置心跳检测机制-->
<heartbeat>select user();</heartbeat>
<!--指定到底哪个服务器来处理dataNode请求-->
<writeHost host = "master" url = "192.168.22.130:3306" user = "root" password = "MyNewPass4!" >
<readHost host = "slave01" url="192.168.22.129:3306" user = "root" password = "MyNewPass4!"></readHost>
</writeHost>
</dataHost>
<dataHost name = "slave01" maxCon = "1000" minCon = "10" balance = "1" writeType = "0" dbType = "mysql" dbDriver = "native">
<!--配置心跳检测机制-->
<heartbeat>select user();</heartbeat>
<!--指定到底哪个服务器来处理dataNode请求-->
<writeHost host = "master" url = "192.168.22.130:3306" user = "root" password = "MyNewPass4!" >
<readHost host = "slave01" url="192.168.22.129:3306" user = "root" password = "MyNewPass4!"></readHost>
</writeHost>
</dataHost>
</mycat:schema>
§ 配置rule.xml文件也不需要发生改变.使用以前的即可
§ 重启mycat服务
重启
./mycat restart
停止
./mycat stop
查看状态
./mycat status
启动
./mycat start
§ 测试时,数据没有同步,手动开启mysql的主从复制功能
查看从服务器中的IO线程 SQL线程
Shiro权限框架
认证:判断用户是否存在 判断账号和密码是否正确
授权:就是给你一些权限,能够访问哪些资源,授权之前先进性认证.
什么是权限管理
权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以 访问而且只能访问自己被授权的资源,不多不少。权限管理几乎出现 在任何系统里面,只要有用户和密码的系统。常用于后台管理系统,
通用权限管理,一般指的是五张表 权限表 角色表 用户表 权限角色表 用户角色表
--->用户登录时,通过用户名--->含有的角色--->查询出含有的权限--->可以操作的资源
之前的项目:智游公寓,智游客户关系管理系统,智游在线视频,智游医院系统,智游众筹
权限管理一般包括用户身份认证和授权两个部分,简称认证授权.
对于需要访问控制的资源,用户需要首先经过身份认证,
认证通过后,用户具有该资源的访问权限
用户的身份认证
认证概念
身份认证就是判断一个用户是否为合法用户的处理过程.
最常用的简单身份认证方式就是通过对用户输入的用户名和口令
查看是否与系统中的储存的用户名和口令一致,来判断用户身份是否正确.
现实中,指纹系统,刷卡系统,本质都是判断用户名和密码是否正确
身份认证的流程
关键对象
□ Subject
主体,访问系统的用户,程序等,一般情况下需要进行认证的都称之为主体
□ Principal
身份信息,是主体进行身份认证的一种表示,一般情况具有唯一性.
□ credential:
凭证信息,是只有主体才知道的安全信息,例如:密码,密钥,口令等
授权
授权即访问控制,就是控制水能够访问哪些资源.
主体进行身份认证后需要分配权限方可访问系统资源.
对于某些资源没有权限是无法访问的.
授权的流程
关键对象
授权可以理解为:谁对什么进行了怎样的操作(主体对资源进行了权限或者许可的哪些操作)
谁:subject:主体 需要访问系统中的资源
什么:Resource 比如:包括资源的类型和资源的实例(资源类型:删除用户 资源实例:只能删除某个或者是某些具体的用户)
怎样的:Permission 权限或者许可,规定了主体对资源的操作许可
注意:权限离开资源没有意义的,通过权限可知主体对系统中的哪些资源都有哪些操作许可
权限分为粗颗粒和细颗粒
粗颗粒权限是指资源类型的权限,细颗粒权限是指资源实例的权限
比如说:添加用户属于资源类型(粗颗粒),具体的某个操作属于资源实例(细颗粒)
比如说:班长可以管理整个班的同学,而组长只能管理分配的组内的某几个人
主体,权限,资源关系图
权限模型
主体权限资源都是是通过数据模型来呈现的
主体(账号密码)
资源(资源的名称,访问的地址)
权限(权限的名称,资源的id)
角色(角色名称)
角色权限关系(角色id 和权限id)
主体和角色关系(主体id和角色id)
在企业开发中,一般情况下会把权限和资源合并成一张表
资源(资源名称,资源访问url地址)
权限(权限的名称,资源id)
合并 :
权限(权限的名称,资源名称,资源的访问url地址)
权限分配
对主体分配权限,主体只允许在自己的权限范围内对资源进行操作
权限分配的数据需要进行持久化,根据模型图来搭建,并将用户的权限信息储存在数据库中
权限控制
用户拥有权限可以操作权限范围内的资源,对于系统来说不直到主体是否拥有访问权限需要对用户的访问进行控制
第一种:基于角色的权限控制
RBAC(基于角色的访问控制),是以角色为中心进行访问控制.
缺点:角色进行访问控制颗粒度较粗,如果主体角色发生变更,那么需要修改原有代码,可扩展性较差
比如说:你是一个群主
第二种:基于资源的权限控制
RBAC(基于资源的访问控制),是以资源为中心进行访问控制.
比如说:主体必须拥有查询工资的权限方可查询员工信息
优点:
权限标识是提前设定好的
查询工资的权限对应的角色--->总经理
查询工资的权限对应的角色--->总经理和部门经理
将查询工资的权限添加到部门经理角色的权限列表中,原有代码不需要发生改变,系统可扩展性较好
权限管理的解决方案
第一种:使用粗颗粒和细颗粒进行控制
第二种:基于url拦截
基于url拦截的是企业中比较常用的解决方案
实现思路:
将系统操作的每个url配置到权限列表中
将权限对应到角色,将角色分配给用户,用户访问系统资源通过Filter进行拦截
过滤器获取到用户访问的url,只要访问的url是用户分配角色中的url则放行让用户继续访问
第三种:使用权限管理框架 Spring security Shiro
使用权限管理框架进行系统开发
也节省系统开发时间
可以节省人力成本
提供了完善的认证和授权功能
有利于系统的维护,方便系统的扩展
shiro
概述:
Apache旗下的一款开源免费的安全框架
他将软件系统的安全认证相关的功能抽离出来,实现用户身份认证,权限授权,加密,会话管理等功能,组成了一个通用的安全认证框架
为什么要学Shiro?
使用shiro可以快速地完成认证,授权等功能的开发,降低系统成本.
shiro使用非常广泛,既可以在web应用中使用,也可以在非web环境中使用,集群分布式中使用也较多
Java领域中的Security使用稍微复杂一点,依赖于Spring环境,而shiro相对较独立一些.
shiro权限框架
subject
主体,外部应用与subject进行交互,subject记录了当前操作用户
用户:可以理解为一个浏览器请求的用户,也可以理解为正在运行的程序
Subject是shiro框架中的一个接口,该接口中定义了很多认证和授权的相关方法,外部程序可以通过subject进行认证和授权,而subject是通过SecurityManager安全管理器进行认证和授权
securityManager
安全管理器,对全部的subject进行安全管理,他是整个shiro的核心,负责对所有subject进行安全管理
通过securityManager可以完成对subject的认证和授权
实质上认证需要通过Authenicator组件来实现的,授权需要通过Authorizer组件实现的,会话管理通过SessionManager组件来实现等…
SecurityManager也是一个接口,继承了Authenicator,Authorizer,SecurityManager这三个接口
Authenicator
认证器,主要是对用户身份进行认证,Authenicator是一个接口,shiro提供了Authenicator实现类
通过它的实现类基本上就可以解决大部分认证问题.
也可以自定义认证器.
Authorizer
授权器,用户通过认证器认证通过,在范围跟系统资源时需要通过授权器,判断用户是否有此资源的操作权限
realm
领域,相当于数据库,通过SecurityManager进行安全认证需要通过读取realm中的信息判断用户是否有此权限资源,
用户身份数据要么在数据库存储,要么就在realm
如果是在数据库中,realm需要从数据库中获取用户的身份信息
SessionManager
会话管理器,shiro框架他不依赖于web容器中的session,shiro它可以在非web应用中使用
也可以在分布式应用中使用,如果是在分布式应用中,可以帮助实现[单点登录].
SessionDAO
会话DAO它可以将session存储到数据库中,也可以通过jdbc把session存储到数据库中
CacheManager
缓存管理器,将用户权限数据存储到缓存中,可以提高访问性能.
Cryptography
密码加密器.
快速入门:
认证:
realm 领域 存储权限资源
securityManager 安全管理器
subject 主体身份信息 账号,密码
开发步骤:
? 导包:
<!--导入shiro相关坐标依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.0</version>
</dependency>
? 新建shiro.ini文件
[users]
# 定义用户名和密码第一个root是账户 第二个root是密码
# 账户名=密码值
root=root
admin=admin
? 新建一个测试类
/**
* 测试认证
*/
@Test
public void test01(){
//realm
//subject
//securityManager
//1.构建SecurityManager实例对象
org.apache.shiro.util.Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
//2.将SecurityManager添加到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//3.获取subject主体信息 从realm中 shiro.ini文件
Subject subject = SecurityUtils.getSubject();
//4.创建token令牌 令牌中包含了用户输入的账户和密码
UsernamePasswordToken token = new UsernamePasswordToken("root", "root");
/**
* 如果账户不存在 程序会抛出 org.apache.shiro.authc.UnknownAccountException:未知账户异常
* 如果账户存在,密码错误 程序会抛出 org.apache.shiro.authc.IncorrectCredentialsException:凭证不正确
*/
try {
//5.进行认证
subject.login(token);//login 登录
System.out.println("认证通过");
}catch (UnknownAccountException e){
System.out.println("账户不存在");
}catch (IncorrectCredentialsException e){
System.out.println("密码拼写错误");
}
//退出 会把认证的信息清除掉
subject.logout();
//判断是否认证通过
boolean authenticated = subject.isAuthenticated();
System.out.println("认证结果为:"+authenticated);//true成功 false失败
}
自定义Realm
认证
开发步骤:
? 第一步:新建自定义类MyRealm
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//1.先获取token的身份信息 用户输入的令牌
String username = (String) token.getPrincipal();
//2.认证 连接数据库 比对账号是否正确 boolean select u_pwd from user where u_name = 'username';
/*boolean authenticated = true/false;
if (authenticated == false){
return null; //没有查询到对应的账户信息 返回一个空
}*/
//如果查到了 就获取到了密码值
String pwd = "root";//root就是查询出来的密码值
SimpleAuthenticationInfo myRealm = new SimpleAuthenticationInfo(username, pwd, "myRealm");
return myRealm;
}
? 第二步:新建shiro_myRealm.ini文件
[main]
myRealm=com.zhiyou.video.utils.MyRealm
securityManager.realms=$myRealm
? 第三步:测试自定义的remal
没变
授权
开发步骤
? 第一步,新建权限资源文件 shiro_privileage.ini文件
[users]
# 账户=密码值,角色名称,角色名称
root=root,role1,role2
admin=admin,role2
[roles]
# 角色名称=权限资源,...,...,...
# 权限资源有两种表示方式:第一种方式:/user/addUser.action
# 第二种方式:user:addUser.action , user:updateUser.action
role1=/user/addUser.action,user/deleteUser.action,/user/updateUser.action
role2=/user/selectAllUser.action
? 第二步:测试
//测试授权
@Test
public void test03(){
//1.构建SecurityManager实例对象
org.apache.shiro.util.Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro_privilege.ini");
SecurityManager securityManager = factory.getInstance();
//2.将SecurityManager添加到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//3.获取subject主体信息 从realm中 shiro.ini文件
Subject subject = SecurityUtils.getSubject();
//4.创建token令牌 令牌中包含了用户输入的账户和密码
UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");
try {
//授权的前提是先进行认证
//5.进行认证
subject.login(token);//login 登录
System.out.println("认证通过");
}catch (UnknownAccountException e){
System.out.println("账户不存在");
}catch (IncorrectCredentialsException e){
System.out.println("密码拼写错误");
}
//判断是否认证通过
boolean authenticated = subject.isAuthenticated();
System.out.println("认证结果为:"+authenticated);//true成功 false失败
//授权 查看该用户是否拥有操作此资源的访问权限
String[] strs = {"/user/selectAllUser.action","/user/updateUser.action"};
boolean[] permitted = subject.isPermitted(strs);
for (int i = 0; i < permitted.length; i++) {
System.out.println(strs[i]+"权限为:"+permitted[i]);//true 有 false 没有
}
}
自定义MyRealm
? 第一步:修改doGetAuthorizationInfo(PrincipalCollection principals)该方法
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//1.获取身份信息
String username = (String) principals.getPrimaryPrincipal();
//2.连接数据库 查询该账号是否存在
/*
2.1 先根据用户名查询 user,role,user_role表
可以获取该用户对应的角色信息
return null;
*/
List<String> roles = new ArrayList<>();
roles.add("CTO");//首席技术官 技术总裁
roles.add("CEO");//首席执行官 执行总裁
/*
2.2 根据角色查询对应的权限资源 role privilege role_privilege
*/
//假如你获取到了数据库对应的权限资源
List<String> privileges = new ArrayList<>();
privileges.add("/user/addUser.action");
privileges.add("/user/selectAllUser.action");
//把角色和权限进行绑定
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加角色信息
info.addRoles(roles);
info.addStringPermissions(privileges);
return info;
}
? 第二步:使用创建的shiro_myRealm.ini文件
? 第三步:测试
//测试自定义MyRealm授权
@Test
public void test04(){
//1.构建SecurityManager实例对象
org.apache.shiro.util.Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro_myRealm.ini");
SecurityManager securityManager = factory.getInstance();
//2.将SecurityManager添加到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//3.获取subject主体信息 从realm中 shiro.ini文件
Subject subject = SecurityUtils.getSubject();
//4.创建token令牌 令牌中包含了用户输入的账户和密码
UsernamePasswordToken token = new UsernamePasswordToken("admin", "root");
//
try {
//授权的前提是先进行认证
//5.进行认证
subject.login(token);//login 登录
System.out.println("认证通过");
}catch (UnknownAccountException e){
System.out.println("账户不存在");
}catch (IncorrectCredentialsException e){
System.out.println("密码拼写错误");
}
//判断是否认证通过
boolean authenticated = subject.isAuthenticated();
System.out.println("认证结果为:"+authenticated);//true成功 false失败
//查看该用户拥有哪些角色信息
boolean ceo = subject.hasRole("CEO");
System.out.println("CEO"+ceo);
//授权 查看该用户是否拥有操作此资源的访问权限
String[] strs = {"/user/selectAllUser.action","/user/updateUser.action"};
boolean[] permitted = subject.isPermitted(strs);
for (int i = 0; i < permitted.length; i++) {
System.out.println(strs[i]+"权限为:"+permitted[i]);//true 有 false 没有
}
}
如果是自定义的MyRealm,那么认证和授权走自定义的MyReamlm类的认证和授权方法
今日内容:
Mycat
分库分表:
读写分离:
原理
实现方式:
开发步骤:
Shiro权限框架
什么是权限管理
用户的身份认证
认证概念
身份认证的流程
关键对象
授权
授权的流程
关键对象
权限分为粗颗粒和细颗粒
主体,权限,资源关系图
权限模型
权限分配
权限控制
第一种:基于角色的权限控制
第二种:基于资源的权限控制
权限管理的解决方案
shiro
概述:
为什么要学Shiro?
shiro权限框架
快速入门:
认证:
开发步骤:
自定义Realm
认证
开发步骤:
授权
开发步骤
自定义MyRealm
Mycat
分库分表:
mycat是一个虚拟的数据库服务器,并不充当存储数据的业务,本身自己链接的时逻辑数据库
数据真实存储在物理数据库上面
读写分离:
原理
让主数据库实现增删改业务,让从数据库实现查询的业务
数据一直想可以通过mysql的主从复制机制来保护数据同步
实现方式:
读写分离需要主从复制,使用mysql自带的主从复制功能即可
开发步骤:
§ 配置server.xml文件 需要配置,保留以前即可,如果有多个逻辑数据库,只需要在schemas里面添加即可.中间用逗号隔开.
§ 配置schema.xml文件
<!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <!-- 配置mycat的物理数据库和逻辑表 <property name = "schema">ZKL_TABLE</property> name = "ZKL_TABLE" 两者之间保持一致 --> <schema name = "ZKL_TABLE" checkSQLschema = "true" sqlMaxLimit = "100"> <table name = "user" dataNode = "dn01" /> <table name = "student" dataNode = "dn02" /> <table name = "dept" dataNode = "dn01,dn02" primaryKey = "d_id" autoIncrement = "true" rule = "mod-long" /> </schema> <!--分库分表配置 分片--> <dataNode name = "dn01" dataHost = "master" database = "ZKL_TABLE"/> <dataNode name = "dn02" dataHost = "slave01" database = "ZKL_TABLE" />
<!--注意事项:尽量schema配置放在一起,dataNode配置放在一起-->
<!--配置物理数据库 真实的数据库--> <dataHost name = "master" maxCon = "1000" minCon = "10" balance = "1" writeType = "0" dbType = "mysql" dbDriver = "native"> <!--配置心跳检测机制--> <heartbeat>select user();</heartbeat> <!--指定到底哪个服务器来处理dataNode请求--> <writeHost host = "master" url = "192.168.22.130:3306" user = "root" password = "MyNewPass4!" > <readHost host = "slave01" url="192.168.22.129:3306" user = "root" password = "MyNewPass4!"></readHost> </writeHost> </dataHost>
<dataHost name = "slave01" maxCon = "1000" minCon = "10" balance = "1" writeType = "0" dbType = "mysql" dbDriver = "native"> <!--配置心跳检测机制--> <heartbeat>select user();</heartbeat> <!--指定到底哪个服务器来处理dataNode请求--> <writeHost host = "master" url = "192.168.22.130:3306" user = "root" password = "MyNewPass4!" > <readHost host = "slave01" url="192.168.22.129:3306" user = "root" password = "MyNewPass4!"></readHost> </writeHost> </dataHost> </mycat:schema> |
§ 配置rule.xml文件也不需要发生改变.使用以前的即可
§ 重启mycat服务
重启
./mycat restart
停止
./mycat stop
查看状态
./mycat status
启动
./mycat start
§ 测试时,数据没有同步,手动开启mysql的主从复制功能
查看从服务器中的IO线程 SQL线程
Shiro权限框架
认证:判断用户是否存在 判断账号和密码是否正确
授权:就是给你一些权限,能够访问哪些资源,授权之前先进性认证.
什么是权限管理
权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以 访问而且只能访问自己被授权的资源,不多不少。权限管理几乎出现 在任何系统里面,只要有用户和密码的系统。常用于后台管理系统,
通用权限管理,一般指的是五张表 权限表 角色表 用户表 权限角色表 用户角色表
--->用户登录时,通过用户名--->含有的角色--->查询出含有的权限--->可以操作的资源
之前的项目:智游公寓,智游客户关系管理系统,智游在线视频,智游医院系统,智游众筹
权限管理一般包括用户身份认证和授权两个部分,简称认证授权.
对于需要访问控制的资源,用户需要首先经过身份认证,
认证通过后,用户具有该资源的访问权限
用户的身份认证
认证概念
身份认证就是判断一个用户是否为合法用户的处理过程.
最常用的简单身份认证方式就是通过对用户输入的用户名和口令
查看是否与系统中的储存的用户名和口令一致,来判断用户身份是否正确.
现实中,指纹系统,刷卡系统,本质都是判断用户名和密码是否正确
身份认证的流程
关键对象
· Subject
主体,访问系统的用户,程序等,一般情况下需要进行认证的都称之为主体
· Principal
身份信息,是主体进行身份认证的一种表示,一般情况具有唯一性.
· credential:
凭证信息,是只有主体才知道的安全信息,例如:密码,密钥,口令等
授权
授权即访问控制,就是控制水能够访问哪些资源.
主体进行身份认证后需要分配权限方可访问系统资源.
对于某些资源没有权限是无法访问的.
授权的流程
关键对象
授权可以理解为:谁对什么进行了怎样的操作(主体对资源进行了权限或者许可的哪些操作)
谁:subject:主体 需要访问系统中的资源
什么:Resource 比如:包括资源的类型和资源的实例(资源类型:删除用户 资源实例:只能删除某个或者是某些具体的用户)
怎样的:Permission 权限或者许可,规定了主体对资源的操作许可
注意:权限离开资源没有意义的,通过权限可知主体对系统中的哪些资源都有哪些操作许可
权限分为粗颗粒和细颗粒
粗颗粒权限是指资源类型的权限,细颗粒权限是指资源实例的权限
比如说:添加用户属于资源类型(粗颗粒),具体的某个操作属于资源实例(细颗粒)
比如说:班长可以管理整个班的同学,而组长只能管理分配的组内的某几个人
主体,权限,资源关系图
权限模型
主体权限资源都是是通过数据模型来呈现的
主体(账号密码)
资源(资源的名称,访问的地址)
权限(权限的名称,资源的id)
角色(角色名称)
角色权限关系(角色id 和权限id)
主体和角色关系(主体id和角色id)
在企业开发中,一般情况下会把权限和资源合并成一张表
资源(资源名称,资源访问url地址)
权限(权限的名称,资源id)
合并 :
权限(权限的名称,资源名称,资源的访问url地址)
权限分配
对主体分配权限,主体只允许在自己的权限范围内对资源进行操作
权限分配的数据需要进行持久化,根据模型图来搭建,并将用户的权限信息储存在数据库中
权限控制
用户拥有权限可以操作权限范围内的资源,对于系统来说不直到主体是否拥有访问权限需要对用户的访问进行控制
第一种:基于角色的权限控制
RBAC(基于角色的访问控制),是以角色为中心进行访问控制.
缺点:角色进行访问控制颗粒度较粗,如果主体角色发生变更,那么需要修改原有代码,可扩展性较差
比如说:你是一个群主
第二种:基于资源的权限控制
RBAC(基于资源的访问控制),是以资源为中心进行访问控制.
比如说:主体必须拥有查询工资的权限方可查询员工信息
优点:
权限标识是提前设定好的
查询工资的权限对应的角色--->总经理
查询工资的权限对应的角色--->总经理和部门经理
将查询工资的权限添加到部门经理角色的权限列表中,原有代码不需要发生改变,系统可扩展性较好
权限管理的解决方案
第一种:使用粗颗粒和细颗粒进行控制
第二种:基于url拦截
基于url拦截的是企业中比较常用的解决方案
实现思路:
将系统操作的每个url配置到权限列表中
将权限对应到角色,将角色分配给用户,用户访问系统资源通过Filter进行拦截
过滤器获取到用户访问的url,只要访问的url是用户分配角色中的url则放行让用户继续访问
第三种:使用权限管理框架 Spring security Shiro
使用权限管理框架进行系统开发
也节省系统开发时间
可以节省人力成本
提供了完善的认证和授权功能
有利于系统的维护,方便系统的扩展
shiro
概述:
Apache旗下的一款开源免费的安全框架
他将软件系统的安全认证相关的功能抽离出来,实现用户身份认证,权限授权,加密,会话管理等功能,组成了一个通用的安全认证框架
为什么要学Shiro?
使用shiro可以快速地完成认证,授权等功能的开发,降低系统成本.
shiro使用非常广泛,既可以在web应用中使用,也可以在非web环境中使用,集群分布式中使用也较多
Java领域中的Security使用稍微复杂一点,依赖于Spring环境,而shiro相对较独立一些.
shiro权限框架
subject
主体,外部应用与subject进行交互,subject记录了当前操作用户
用户:可以理解为一个浏览器请求的用户,也可以理解为正在运行的程序
Subject是shiro框架中的一个接口,该接口中定义了很多认证和授权的相关方法,外部程序可以通过subject进行认证和授权,而subject是通过SecurityManager安全管理器进行认证和授权
securityManager
安全管理器,对全部的subject进行安全管理,他是整个shiro的核心,负责对所有subject进行安全管理
通过securityManager可以完成对subject的认证和授权
实质上认证需要通过Authenicator组件来实现的,授权需要通过Authorizer组件实现的,会话管理通过SessionManager组件来实现等…
SecurityManager也是一个接口,继承了Authenicator,Authorizer,SecurityManager这三个接口
Authenicator
认证器,主要是对用户身份进行认证,Authenicator是一个接口,shiro提供了Authenicator实现类
通过它的实现类基本上就可以解决大部分认证问题.
也可以自定义认证器.
Authorizer
授权器,用户通过认证器认证通过,在范围跟系统资源时需要通过授权器,判断用户是否有此资源的操作权限
realm
领域,相当于数据库,通过SecurityManager进行安全认证需要通过读取realm中的信息判断用户是否有此权限资源,
用户身份数据要么在数据库存储,要么就在realm
如果是在数据库中,realm需要从数据库中获取用户的身份信息
SessionManager
会话管理器,shiro框架他不依赖于web容器中的session,shiro它可以在非web应用中使用
也可以在分布式应用中使用,如果是在分布式应用中,可以帮助实现[单点登录].
SessionDAO
会话DAO它可以将session存储到数据库中,也可以通过jdbc把session存储到数据库中
CacheManager
缓存管理器,将用户权限数据存储到缓存中,可以提高访问性能.
Cryptography
密码加密器.
快速入门:
认证:
realm 领域 存储权限资源
securityManager 安全管理器
subject 主体身份信息 账号,密码
开发步骤:
· 导包:
<!--导入shiro相关坐标依赖--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.0</version> </dependency>
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.3.0</version> </dependency>
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.0</version> </dependency> |
· 新建shiro.ini文件
[users] # 定义用户名和密码第一个root是账户 第二个root是密码 # 账户名=密码值 root=root admin=admin |
· 新建一个测试类
/** * 测试认证 */ @Test public void test01(){ //realm //subject //securityManager //1.构建SecurityManager实例对象 org.apache.shiro.util.Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); //2.将SecurityManager添加到运行环境中 SecurityUtils.setSecurityManager(securityManager); //3.获取subject主体信息 从realm中 shiro.ini文件 Subject subject = SecurityUtils.getSubject(); //4.创建token令牌 令牌中包含了用户输入的账户和密码 UsernamePasswordToken token = new UsernamePasswordToken("root", "root");
/** * 如果账户不存在 程序会抛出 org.apache.shiro.authc.UnknownAccountException:未知账户异常 * 如果账户存在,密码错误 程序会抛出 org.apache.shiro.authc.IncorrectCredentialsException:凭证不正确 */ try { //5.进行认证 subject.login(token);//login 登录 System.out.println("认证通过"); }catch (UnknownAccountException e){ System.out.println("账户不存在"); }catch (IncorrectCredentialsException e){ System.out.println("密码拼写错误"); }
//退出 会把认证的信息清除掉 subject.logout();
//判断是否认证通过 boolean authenticated = subject.isAuthenticated(); System.out.println("认证结果为:"+authenticated);//true成功 false失败 } |
自定义Realm
认证
开发步骤:
· 第一步:新建自定义类MyRealm
//认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //1.先获取token的身份信息 用户输入的令牌 String username = (String) token.getPrincipal(); //2.认证 连接数据库 比对账号是否正确 boolean select u_pwd from user where u_name = 'username'; /*boolean authenticated = true/false; if (authenticated == false){ return null; //没有查询到对应的账户信息 返回一个空 }*/ //如果查到了 就获取到了密码值 String pwd = "root";//root就是查询出来的密码值 SimpleAuthenticationInfo myRealm = new SimpleAuthenticationInfo(username, pwd, "myRealm"); return myRealm; } |
· 第二步:新建shiro_myRealm.ini文件
[main] myRealm=com.zhiyou.video.utils.MyRealm securityManager.realms=$myRealm |
· 第三步:测试自定义的remal
没变 |
授权
开发步骤
· 第一步,新建权限资源文件 shiro_privileage.ini文件
[users] # 账户=密码值,角色名称,角色名称 root=root,role1,role2 admin=admin,role2
[roles] # 角色名称=权限资源,...,...,... # 权限资源有两种表示方式:第一种方式:/user/addUser.action # 第二种方式:user:addUser.action , user:updateUser.action role1=/user/addUser.action,user/deleteUser.action,/user/updateUser.action role2=/user/selectAllUser.action |
· 第二步:测试
//测试授权 @Test public void test03(){ //1.构建SecurityManager实例对象 org.apache.shiro.util.Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro_privilege.ini"); SecurityManager securityManager = factory.getInstance(); //2.将SecurityManager添加到运行环境中 SecurityUtils.setSecurityManager(securityManager); //3.获取subject主体信息 从realm中 shiro.ini文件 Subject subject = SecurityUtils.getSubject(); //4.创建token令牌 令牌中包含了用户输入的账户和密码 UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin"); try { //授权的前提是先进行认证 //5.进行认证 subject.login(token);//login 登录 System.out.println("认证通过"); }catch (UnknownAccountException e){ System.out.println("账户不存在"); }catch (IncorrectCredentialsException e){ System.out.println("密码拼写错误"); }
//判断是否认证通过 boolean authenticated = subject.isAuthenticated(); System.out.println("认证结果为:"+authenticated);//true成功 false失败
//授权 查看该用户是否拥有操作此资源的访问权限 String[] strs = {"/user/selectAllUser.action","/user/updateUser.action"}; boolean[] permitted = subject.isPermitted(strs);
for (int i = 0; i < permitted.length; i++) { System.out.println(strs[i]+"权限为:"+permitted[i]);//true 有 false 没有 }
} |
自定义MyRealm
· 第一步:修改doGetAuthorizationInfo(PrincipalCollection principals)该方法
//授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //1.获取身份信息 String username = (String) principals.getPrimaryPrincipal(); //2.连接数据库 查询该账号是否存在 /* 2.1 先根据用户名查询 user,role,user_role表 可以获取该用户对应的角色信息 return null; */ List<String> roles = new ArrayList<>(); roles.add("CTO");//首席技术官 技术总裁 roles.add("CEO");//首席执行官 执行总裁 /* 2.2 根据角色查询对应的权限资源 role privilege role_privilege */ //假如你获取到了数据库对应的权限资源 List<String> privileges = new ArrayList<>(); privileges.add("/user/addUser.action"); privileges.add("/user/selectAllUser.action");
//把角色和权限进行绑定 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //添加角色信息 info.addRoles(roles); info.addStringPermissions(privileges);
return info; } |
· 第二步:使用创建的shiro_myRealm.ini文件
· 第三步:测试
//测试自定义MyRealm授权 @Test public void test04(){ //1.构建SecurityManager实例对象 org.apache.shiro.util.Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro_myRealm.ini"); SecurityManager securityManager = factory.getInstance(); //2.将SecurityManager添加到运行环境中 SecurityUtils.setSecurityManager(securityManager); //3.获取subject主体信息 从realm中 shiro.ini文件 Subject subject = SecurityUtils.getSubject(); //4.创建token令牌 令牌中包含了用户输入的账户和密码 UsernamePasswordToken token = new UsernamePasswordToken("admin", "root");
//
try { //授权的前提是先进行认证 //5.进行认证 subject.login(token);//login 登录 System.out.println("认证通过"); }catch (UnknownAccountException e){ System.out.println("账户不存在"); }catch (IncorrectCredentialsException e){ System.out.println("密码拼写错误"); }
//判断是否认证通过 boolean authenticated = subject.isAuthenticated(); System.out.println("认证结果为:"+authenticated);//true成功 false失败
//查看该用户拥有哪些角色信息 boolean ceo = subject.hasRole("CEO"); System.out.println("CEO"+ceo);
//授权 查看该用户是否拥有操作此资源的访问权限 String[] strs = {"/user/selectAllUser.action","/user/updateUser.action"}; boolean[] permitted = subject.isPermitted(strs);
for (int i = 0; i < permitted.length; i++) { System.out.println(strs[i]+"权限为:"+permitted[i]);//true 有 false 没有 } } |
如果是自定义的MyRealm,那么认证和授权走自定义的MyReamlm类的认证和授权方法