1.Shrio 授权的流程
SecurityManage (shiro环境)---->Subject.isPermission()(授权)----->SecurityManage.isPermission()(主体将
授权操作交给安全管理器)----->Authorizer(接口:正在授权调用数据源)------>Realm(数据源:查询权限)
2.Relam代码
/**
* 自定义shiro Relam
* @author LSQ
* by QQ237442461 2016-10-7
*/
public class CustomRelam extends AuthorizingRealm{
@Resource(name="userService")
private UserService userService;
@Resource(name="permissionService")
private PermissionService permissionService;
@Override
public String getName() {
return "customRealm";
}
// 支持什么类型的token,选择 UsernamePasswordToken
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//从token中获取用户的身份信息
String username = (String) token.getPrincipal();
User user = null;
try {
user = this.userService.queryByUserName(username);
} catch (Exception e) {
e.printStackTrace();
}
if(user == null){
return null;
}
return new SimpleAuthenticationInfo(user, user.getPassword().toCharArray(), getName());
}
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取认证过后的用户信息
User user = (User) principals.getPrimaryPrincipal();
Long userId = user.getId();
List<Permission> permissions = null;
try {
permissions = this.permissionService.queryPermissionListByUserId(userId);
} catch (Exception e) {
e.printStackTrace();
}
//构建shiro授权信息
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (Permission permission : permissions) {
simpleAuthorizationInfo.addStringPermission(permission.getPercode());
}
return simpleAuthorizationInfo;
}
}
3.权限的使用
shiro的权限可用通过注解式和jsp标签式进行控制。
a: 注解式
// 查询商品列表
@RequestMapping("/queryItem")
@RequiresPermissions("item:query")
public ModelAndView queryItem() throws Exception {
上边代码@RequiresPermissions("item:query")表示必须拥有“item:query”权限方可执行。
注解式需要开启springmvc对shiro注解的支持。
<!-- 开启aop,对类代理 -->
<aop:config proxy-target-class="true"></aop:config>
<!-- 开启shiro注解支持 -->
<bean
class="
org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
b: jsp标签式
Jsp页面添加:
<%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %>
标签名称 | 标签条件(均是显示标签内容) |
<shiro:authenticated> | 登录之后 |
<shiro:notAuthenticated> | 不在登录状态时 |
<shiro:guest> | 用户在没有RememberMe时 |
<shiro:user> | 用户在RememberMe时 |
<shiro:hasAnyRoles name="abc,123" > | 在有abc或者123角色时 |
<shiro:hasRole name="abc"> | 拥有角色abc |
<shiro:lacksRole name="abc"> | 没有角色abc |
<shiro:hasPermission name="abc"> | 拥有权限资源abc |
<shiro:lacksPermission name="abc"> | 没有abc权限资源 |
<shiro:principal> | 显示用户身份名称 |
<shiro:principal property="username"/> 显示用户身份中的属性值
如果有商品修改权限页面显示“修改”链接。
<shiro:hasPermission name="item:update">
<a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a>
</shiro:hasPermission>
值得注意:Shiro 在每次遇到shiro注解或者shiro的jsp标签的时候,每次都会访问自定义的Reaml,这样一来每次都查数据库,所以我们应该将它放在缓冲中,每次遇到注解或者shiro标签的时候只需要从缓冲中查找即可,缓冲是存储在内存,数据库持久化数据是写在硬盘上,显而易见,速度上会有不少的提升。当授权信息改变的时候,我们可以清空缓冲。了解更多shiro技术,请持续关注zlt尼玛银行。