权限认证核心要素
权限认证,也就是访问控制,即在应用中控制谁能访问哪些资源。
在权限认证中,最核心的三个要素是:权限,角色和用户;
权限,即操作资源的权利,比如访问某个页面,以及对某个模块的数据的添加,修改,删除,查看的权利;
角色,是权限的集合,一中角色可以包含多种权限;
用户,在 Shiro 中,代表访问系统的用户,即 Subject;
授权
3种授权的方式:
编程性授权,注解式授权,jsp标签授权,下面通过实例一一介绍:
也可以查看:官方文档
编程性授权
1 基于角色的访问控制
2 基于权限的访问控制
基于角色的访问控制
为了便于进行身份验证,我们把上一篇说的整个的身份认证的过程封装成一个静态方法,3个参数:shiro.ini配置文件,userName,password,返回一个Subject(当前用户) :
public class ShiroUtil {
public static Subject login(String shiro_config,String userName,String password) {
//读取配置文件,初始化SecurityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory(shiro_config);
//获取SecurityManager实例
SecurityManager securityManager = factory.getInstance();
//把securityManager实例绑定到SecurityUtils
SecurityUtils.setSecurityManager(securityManager);
//创建Token令牌,用户/密码
UsernamePasswordToken token = new UsernamePasswordToken(userName,password);
//得到当前执行的用户
Subject currentUser = SecurityUtils.getSubject();
try {
//身份认证
currentUser.login(token);
System.out.println("身份认证成功!");
}catch(AuthenticationException e) {
e.printStackTrace();
System.out.println("身份认证失败!");
}
return currentUser;
}
}
先进行基于角色的权限认证:
新建shiro_role.ini:
#定义两个用户,分别有不同的角色
#java用户有role1,role2两个角色
#12用户只有role1一个角色
[users]
java=1234,role1,role2
12=12.role1
shiro提供方法:
hasRole方法:参数是String roleName,用户有该角色返回true,没有返回false.
@Test
public void hasRole() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "12", "12");
System.out.println(currentUser.hasRole("role2")?"用户有role2角色":"用户没有role2角色");
currentUser.logout();
}
hasRoles(List<String>):将要判断的角色放到数组里,判断结果返回布尔型数组:
@Test
public void hasRoles() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "12", "12");
boolean result[] = currentUser.hasRoles(Arrays.asList("role1","role2"));
System.out.println(result[0]?"用户有role1角色":"用户没有role1角色");
System.out.println(result[1]?"用户有role2角色":"用户没有role2角色");
currentUser.logout();
}
hasAllRoles:参数为String数组,只有这些角色用户都有,返回true,不全有返回false
@Test
public void hasAllRoles() {
Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "12", "12");
System.out.println(currentUser.hasAllRoles(Arrays.asList("role1","role2"))?"用户有角色1和角色2":"用户不全有角色1和角色2");
currentUser.logout();
}
shiro还提供了一类方法:
不满足,直接抛出异常。没有返回值。
@Test
public void checkRole() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "12", "12");
currentUser.checkRole("role2");
currentUser.logout();
}
@Test
public void checkRoles1() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "12", "12");
currentUser.checkRoles(Arrays.asList("role1","role2"));
currentUser.logout();
}
@Test
public void checkRoles2() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "12", "12");
currentUser.checkRoles("role1","role2");
currentUser.logout();
}
基于权限的访问控制
新建shiro配置文件:shiro_permission.ini:
[users]
java=1234,role1,role2
12=12,role1
[roles]
role1=user:select
role2=user:user:add,user:delete,user:update
shiro提供的判断方法:
isPermitted两个重载的方法:
一个参数为Perminssion,但一般还是采用String作为参数,
一个参数为字符串数组,返回布尔类型字符串数组
@Test
public void isPermittedTest() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "12", "12");
System.out.println(currentUser.isPermitted("user:update")?"用户有user:update权限":"用户没有user:update权限");
currentUser.logout();
}
@Test
public void isPermittedTest2() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_permission.ini", "12", "12");
boolean []result = currentUser.isPermitted("user:select","user:add","user:delete","user:update");
System.out.println(result[0]?"用户有user:select权限":"用户没有user:select权限");
System.out.println(result[1]?"用户有user:add权限":"用户没有user:add权限");
System.out.println(result[2]?"用户有user:delete权限":"用户没有user:delete权限");
System.out.println(result[3]?"用户有user:update权限":"用户没有user:update权限");
currentUser.logout();
}
isPermittedAll:方法参数是一串字符,如果权限都具备,才返回true,否则返回false.
@Test
public void isPermittedAllTest() {
//Subject currentUser = ShiroUtil.login("classpath:shiro_role.ini", "java", "1234");
Subject currentUser = ShiroUtil.login("classpath:shiro_permission.ini", "12", "12");
boolean result = currentUser.isPermittedAll("user:select","user:add","user:delete","user:update");
System.out.println(result?"用户有user:select,add,delete,update权限":"用户不全有user:select,add,delete,update权限");
currentUser.logout();
}
还有:
checkPermission(权限),如果没有,直接抛出异常
checkPermissions("权限1","权限2","权限3"),只有当权限都具备,不满足抛出异常。
总结:
这一篇主要介绍:编程性授权方式;
一个是基于角色的,一个是基于权限的。
基于角色的,判断用户是否具备某种角色,判断方法有两类:
hasRole("某角色") hasRoles(字符串数组) 返回boolean型数组, hasAllRoles(字符串数组),只有都具备角色时,返回true.
checkRole("某角色") checkRoles(字符串数组)与checkRoles("","","")一个意思,就是参数类型不同。
基于权限的,判断用户是否拥有权限:判断方法有两类:
isPermitted("权限1") isPermitted("","","")返回数组 isPermittedAll("","")只有权限都具备才返回true.
checkPermission("") checkPermissions("","","")只有当用户所有权限都满足,否则抛出异常。