什么是授权
授权就是在认证的基础上给用户进行角色和权限的授予。权限定义了一个用户是否可以执行某个操作。角色是一组权限的集合,我们通常把一组权限绑定到一种角色上,再吧一个或者多个角色赋给一个用户,这样就是实现了权限的控制。
Shiro授权核心概念
权限 : 即操作资源的权利,比如访问某个页面,以及对某个模块的数据的添加,修改,删除,查看的权利
角色 : 是权限的集合,一种角色可以包含多种权限
用户 : 在 Shiro 中,代表访问系统的用户,即Subject
Shiro授权流程
Shiro授权就是对subject主体进行授权,subject委托给SecurityManager执行授权,而SecurityManager又通过ModelarRealmAuthorizer调用doGetAuthorizationInfo方法执行自定义Realm从数据库查询权限数据,然后ModelarRealmAuthorizer又调用PermissionResolver进行权限串比对,如果“permission串”再realm查询到的权限数据数据汇总,说明用户访问permission串有权限否则没有权限,抛出异常。
Shiro授权三种方式
编程式:通过写if/else 授权代码块完成:
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有权限
} else {
//无权限
}
注解式:通过在执行的Java方法上放置相应的注解完成:
@RequiresRoles("admin")
public void hello() {
//有权限
}
JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:
<shiro:hasRole name="admin">
<!— 有权限—>
</shiro:hasRole>
自定义Realm
在Shiro身份认证这篇文章中的自定义Realm(myRealm)中重写了方法doGetAuthenticationInfo用于身份认证;为了实现授权,现在需要重写doGetAuthorizationInfo方法。
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
String sysUserId = ((SysUser)principals.getPrimaryPrincipal()).getId();
// 根据用户ID查询角色(role),放入到Authorization里
Result<List<SysRole>> rolesResult = sysUserService.getRolesByUserId(sysUserId);
if(!ResultConstants.RESULT_CODE_SUCCESS.equals(rolesResult.getResultCode())) {
throw new RuntimeException(ResultConstants.RESULT_CDESC_FAILED);
}
authorizationInfo.setRoles(rolesResult.getResultData().stream().map(SysRole::getRoleName).collect(Collectors.toSet()));
// 根据用户ID查询权限(permission),放入到Authorization里。
Result<List<SysMenu>> menuResult = sysUserService.getMenusByUserId(sysUserId);
if(!ResultConstants.RESULT_CODE_SUCCESS.equals(menuResult.getResultCode())) {
throw new RuntimeException(ResultConstants.RESULT_CDESC_FAILED);
}
authorizationInfo.setStringPermissions(menuResult.getResultData().stream().map(SysMenu::getShiroFlag).filter(StringUtils::isNotBlank).collect(Collectors.toSet()));
return authorizationInfo;
}
编程方式
项目中实际上没有用到编程方式授权,所以还有待学习,编程方式实现shiro授权可以参考:添加链接描述
附上shiro授权demo:链接:https://pan.baidu.com/s/1aq8LHoXTxtTYzyFXS-BL7Q 密码:81q9
注解方式
@RequiresAuthentication 验证用户是否登录
@RequiresUser 当前用户已经验证过了或则记住我了
@RequiresGuest 是否是游客身份
@RequiresRoles 判断subject中有aRoleName角色才可以访问方法someMethod: @RequiresRoles({“admin”})
@RequiresPermissions需要拥有权限:@RequiresPermissions({“file:read”, “write:aFile.txt”} )
例子1:
@RequiresRoles注解要求当前subject具有所指定的admin角色才可以执行,否则不会执行改方法并抛出AuthorizationException。
@RequiresRoles("administrator")
public void deleteUser(User user) {
//此方法仅由管理员调用
}
使用@RequiresRoles注解的方式大致等同于以下编码方式实现的逻辑:
public void deleteUser(User user) {
Subject currentUser = SecurityUtils.getSubject();
if (!subject.hasRole("administrator")) {
throw new AuthorizationException(...);
}
//主体保证在这里是“管理员”
...
}
例子2:
@RequiresPermissions注解要求当前subject具有"account:create"创建account许可
@RequiresPermissions("account:create")
public void createAccount(Account account) {
//此创建帐户的方法仅由主体“允许创建帐户”可调用
}
使用@RequiresPermissions注解大致等同于以下用编程方式实现的逻辑
public void createAccount(Account account) {
Subject currentUser = SecurityUtils.getSubject();
if (!subject.isPermitted("account:create")) {
throw new AuthorizationException(...);
}
//保证在这里允许主体
}
JSP标签
需求:利用shiro的jsp标签实现对操作按钮的控制
jsp页面
{{if delHidden}}
<shiro:hasPermission name="event:register:edit">
<input type="button" class="gray_btn mr10" onclick="toEdit('{{:id}}','edit')" value="编辑">
</shiro:hasPermission>
<shiro:hasPermission name="event:register:del">
<input type="button" class="gray_btn mr10" onclick="toDelete('{{:id}}')" value="删除">
</shiro:hasPermission>
{{else}}
<shiro:hasPermission name="event:register:look">
<input type="button" class="gray_btn mr10" onclick="toEdit('{{:id}}','look')" value="查看">
</shiro:hasPermission>
{{/if}}
数据库设计
利用shiro:hasPermission标签,从数据库查询数据,如果数据库存在相应的标签name,此操作按钮显示,如果不存在,操作按钮隐藏