什么是权限管理
一、使用ini完成认证,入门
1、创建shiro.ini文件,模拟数据库查询
#固定写法-创建用户对象
[users]
# 账号=密码
zhangchao=666
2、测试类
package com.zhangchao.shiro.study;
import org.apache.shiro.SecurityUtils;
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;
import org.junit.Test;
/**
* 〈〉
*
* @author zc
* @create 2018/11/20
*/
public class ShiroTest {
@Test
public void testLogin(){
//1、创建SecurityManager工厂,加载配置文件,创建工厂对象
Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = managerFactory.getInstance();
//3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登陆主体
Subject subject = SecurityUtils.getSubject();
//5、收集主体登陆的身份凭证,即账号,密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
//6、主体登陆
try {
subject.login(token);
}catch (Exception e){
e.printStackTrace();
}
//验证是否登陆 true为登陆
System.out.println("验证是否登陆 : "+ subject.isAuthenticated());
//7、登出
subject.logout();
//验证是否登出 false为登出
System.out.println("验证是否登出 : "+ subject.isAuthenticated());
}
}
二 、自定义realm
1、自定义reaml,继承AuthorizingRealm 重写三个方法,getName、doGetAuthorizationIngo、doGetAuthenticationInfo
package com.zhangchao.shiro.study;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* 〈自定义realm〉
*
* @author 22902
* @create 2018/11/20
*/
public class MyRealm extends AuthorizingRealm {
@Override
public String getName() {
return "myRealm";
}
/**
* 授权操作
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
/**
* 认证操作
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//token 表示登陆时包装的username和password
//通过用户名到数据库中查询用户信息,封装成一个authenticationInfo 对象返回,方便认证器进行对比
//获取token中用户名
String username = (String) token.getPrincipal();
System.out.println(username);
//通过用户名查询数据库,将改用户对应数据返回账号密码
if (!"zhangchao".equals(username)){
return null;
}
String password = "666";
//info对象表示realm登陆对比信息,参数1:用户信息(真实登陆中是登陆对象user对象),参数2:密码,参数3:当前realm名
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
return info;
}
}
2、配置ini文件,指定使用自定义realm
#声明一个realm
myRealm=com.zhangchao.shiro.study.MyRealm
#这里就是我们注入realm的地方
securityManager.realms=$myRealm
3、加载配置文件shiro-realm.ini ,执行登陆操作
@Test
public void testLogin(){
//1、创建SecurityManager工厂,加载配置文件,创建工厂对象
Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = managerFactory.getInstance();
//3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登陆主体
Subject subject = SecurityUtils.getSubject();
//5、收集主体登陆的身份凭证,即账号,密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
//6、主体登陆
try {
subject.login(token);
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
catch (Exception e){
e.printStackTrace();
}
//验证是否登陆
System.out.println("验证是否登陆 : "+ subject.isAuthenticated());
//7、登出
subject.logout();
//验证是否登出
System.out.println("验证是否登出 : "+ subject.isAuthenticated());
}
三、加密realm登入登出
测试下md5
package com.zhangchao.shiro.study;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.junit.Test;
/**
* 〈MD5加密〉
*
* @author 22902
* @create 2018/11/21
*/
public class MD5Test {
@Test
public void md5Test() {
//密码 明文
String password = "666";
//加密md5 fae0b27c451c728867a567e8c1bb4e53
Md5Hash md5Hash = new Md5Hash(password);
System.out.println(md5Hash);
//加密md5 + 盐 8ab1db3f57dfd36248b1dcd7adc12ab0
md5Hash = new Md5Hash(password,"zhangchao");
System.out.println(md5Hash);
//加密md5 + 盐 + 散列次数 e925117800d6e0b60098b681809b3789
md5Hash = new Md5Hash(password,"zhangchao",5);
System.out.println(md5Hash);
}
}
1、自定义加密之后realm
package com.zhangchao.shiro.study;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
/**
* 〈〉
*
* @author 22902
* @create 2018/11/21
*/
public class PasswordRealm extends AuthorizingRealm {
@Override
public String getName() {
return "passwordRealm";
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//token 表示登陆时包装的username和password
//通过用户名到数据库中查询用户信息,封装成一个authenticationInfo 对象返回,方便认证器进行对比
//获取token中用户名
String username = (String) token.getPrincipal();
System.out.println(username);
//通过用户名查询数据库,将改用户对应数据返回账号密码
if (!"zhangchao".equals(username)){
return null;
}
//模拟数据库中保存加密之后密文: 666 + 账号(盐) + 三列次数
String password = "e925117800d6e0b60098b681809b3789";
//info对象表示realm登陆对比信息,参数1:用户信息(真实登陆中是登陆对象user对象),参数2:密码,参数3:盐,参数4:当前realm名
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, ByteSource.Util.bytes("zhangchao"), getName());
return info;
}
}
2、配置ini配置文件
[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数 md5| sha
credentialsMatcher.hashIterations=5
#将凭证匹配器设置到realm
myRealm=com.zhangchao.shiro.study.PasswordRealm
myRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$myRealm
3、测试
package com.zhangchao.shiro.study;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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;
import org.junit.Test;
/**
* 〈〉
*
* @author 22902
* @create 2018/11/20
*/
public class ShiroTest {
@Test
public void testLogin(){
//1、创建SecurityManager工厂,加载配置文件,创建工厂对象
Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-cryptography.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = managerFactory.getInstance();
//3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登陆主体
Subject subject = SecurityUtils.getSubject();
//5、收集主体登陆的身份凭证,即账号,密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
//6、主体登陆
try {
subject.login(token);
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
catch (Exception e){
e.printStackTrace();
}
//验证是否登陆
System.out.println("验证是否登陆 : "+ subject.isAuthenticated());
//7、登出
subject.logout();
//验证是否登出
System.out.println("验证是否登出 : "+ subject.isAuthenticated());
}
}
四、rbac权限模型理解
五、ini方式检查用户拥有权限
授权方式(三种)
权限表达式定义
1、配置ini文件
[users]
# 用户zhagnchao的密码为666,拥有role1和role2两个角色
zhangchao=666,role1,role2
lisi=888,role2
[roles]
#角色role1对资源user拥有create、update权限
role1=user:create,user:update
#角色role2对资源user拥有create、delete权限
role2=user:create,user:delete
#角色role3对资源拥有create权限
role3=user:create
2、加载配置文件,检查是否拥有角色
package com.zhangchao.shiro.study;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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;
import org.junit.Test;
import java.util.Arrays;
/**
* 〈〉
*
* @author 22902
* @create 2018/11/20
*/
public class ShiroTest {
@Test
public void testLogin(){
//1、创建SecurityManager工厂,加载配置文件,创建工厂对象
Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = managerFactory.getInstance();
//3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登陆主体
Subject subject = SecurityUtils.getSubject();
//5、收集主体登陆的身份凭证,即账号,密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
//6、主体登陆
try {
subject.login(token);
//进行授权操作时前提:用户必须通过认证
//判断用户是否拥有某个角色
boolean a = subject.hasRole("role1");
System.out.println("用户是否有role1角色 :" + a);
//判断当前用户是否拥有一些角色,true表示全部拥有,false表示bu全部拥有
boolean b = subject.hasAllRoles(Arrays.asList("role1", "role2"));
System.out.println("用户是否有role1、role2角色 :" + b);
//判断当前用户是否拥有一些角色,返回boolean数组,true表示拥有,false表示没有
boolean[] c = subject.hasRoles(Arrays.asList("role1", "role2","role3"));
System.out.println("用户是否有role1、role2角色 :" + Arrays.toString(c));
//判断当前用户是否拥有某个角色,如果拥有该角色,不做任何操作,如果没有,报错UnauthorizedException
// subject.checkRoles("role1","role2","role3");
subject.checkRole("role2");
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
catch (Exception e){
e.printStackTrace();
}
//验证是否登陆
System.out.println("验证是否登陆 : "+ subject.isAuthenticated());
//7、登出
subject.logout();
//验证是否登出
System.out.println("验证是否登出 : "+ subject.isAuthenticated());
}
}
六、ini方式检查用户拥有权限
1、ini配置文件,跟五中是一样的
2、加载配置文件,检查是否拥有权限
package com.zhangchao.shiro.study;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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;
import org.junit.Test;
import java.util.Arrays;
/**
* 〈〉
*
* @author 22902
* @create 2018/11/20
*/
public class ShiroTest {
@Test
public void testLogin(){
//1、创建SecurityManager工厂,加载配置文件,创建工厂对象
Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = managerFactory.getInstance();
//3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登陆主体
Subject subject = SecurityUtils.getSubject();
//5、收集主体登陆的身份凭证,即账号,密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
//6、主体登陆
try {
subject.login(token);
//进行授权操作时前提:用户必须通过认证
//判断当前用户是否拥有某个权限,true表示拥有,false表示没有
boolean a = subject.isPermitted("user:create");
System.out.println("当前用户是否拥有权限: "+a);
//判断当前用户是否拥有某个权限,true表示都拥有,false表示不全部拥有
boolean b = subject.isPermittedAll("user:create", "user:update","user:delete");
System.out.println("当前用户是否拥有权限: "+b);
//判断当前用户是否拥有某个权限,返回boolean数组,true表示都拥有,false表示不拥有
boolean[] booleans = subject.isPermitted("user:create", "user:update");
System.out.println(Arrays.toString(booleans));
//判断当前用户是否拥有某个权限,如果没有报错UnauthorizedException,有不操作
subject.checkPermission("user:create");
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
catch (Exception e){
e.printStackTrace();
}
//验证是否登陆
System.out.println("验证是否登陆 : "+ subject.isAuthenticated());
//7、登出
subject.logout();
//验证是否登出
System.out.println("验证是否登出 : "+ subject.isAuthenticated());
}
}
七、自定义realm授权
1、自定义PermissionRealm类,继承AuthorizingRealm,重写三个方法,getName、doGetAuthorizationIngo、doGetAuthenticationInfo
package com.zhangchao.shiro.study;
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;
import java.util.ArrayList;
import java.util.List;
/**
* 〈自定义realm〉
*
* @author 22902
* @create 2018/11/20
*/
public class PermissionRealm extends AuthorizingRealm {
@Override
public String getName() {
return "PermissionRealm";
}
/**
* 授权操作
* @param principal 用户凭证信息
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
//当前用户信息,用户凭证
String username = (String) principal.getPrimaryPrincipal();
//模拟查询数据库,查询用户实现指定角色,权限
List<String> roles = new ArrayList<>();
List<String> permissions = new ArrayList<>();
//假设用户再数据库中有role1角色
roles.add("role1");
//假设用户在数据库中有user:create权限
permissions.add("user:create");
//返回用户在数据库中的权限及角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissions);
info.addRoles(roles);
return info;
}
/**
* 认证操作
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//token 表示登陆时包装的username和password
//通过用户名到数据库中查询用户信息,封装成一个authenticationInfo 对象返回,方便认证器进行对比
//获取token中用户名
String username = (String) token.getPrincipal();
System.out.println(username);
//通过用户名查询数据库,将改用户对应数据返回账号密码
if (!"zhangchao".equals(username)){
return null;
}
String password = "666";
//info对象表示realm登陆对比信息,参数1:用户信息(真实登陆中是登陆对象user对象),参数2:密码,参数3:当前realm名
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
return info;
}
}
2、配置ini文件 shiro-permission-realm.ini
#声明一个realm
myRealm=com.zhangchao.shiro.study.PermissionRealm
#这里就是我们注入realm的地方
securityManager.realms=$myRealm
3、加载配置文件,测试
package com.zhangchao.shiro.study;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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;
import org.junit.Test;
/**
* 〈〉
*
* @author 22902
* @create 2018/11/20
*/
public class ShiroTest {
@Test
public void testLogin(){
//1、创建SecurityManager工厂,加载配置文件,创建工厂对象
Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-permission-realm.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = managerFactory.getInstance();
//3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登陆主体
Subject subject = SecurityUtils.getSubject();
//5、收集主体登陆的身份凭证,即账号,密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
//6、主体登陆
try {
subject.login(token);
boolean a = subject.isPermitted("user:create");
System.out.println("是否拥有权限: "+a);
boolean b = subject.hasRole("role1");
System.out.println("是否拥有角色: "+b);
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
catch (Exception e){
e.printStackTrace();
}
//验证是否登陆
System.out.println("验证是否登陆 : "+ subject.isAuthenticated());
//7、登出
subject.logout();
//验证是否登出
System.out.println("验证是否登出 : "+ subject.isAuthenticated());
}
}
授权过程如下图
到现在基础篇写完了,这也是我自己学习视频并实践的结果,每天进步一点点,每天学习一点点,努力给我爱的人更好的未来!
感谢姚老师 ,视频地址点击进入