授权管理,三种方式,其中注解和jsp的方式在开发中用得比较的多,但是对于编程的方式完成注解,在实际开发中,用得不是特别多。这一节,讲解shiro如何完成授权的,授权操作,需要在Reaml中,实现doGetAuthorizationInfo 方法,多Reaml的情况下, 只要一个Reaml中满足条件,就会执行
源码地址
https://gitee.com/yellowcong/shior-dmeo/tree/master/test
Shiro的授权三种方式
1、编程方式
2、注解方式
3、jsp标签
授权
授权的时候,需要实现doGetAuthorizationInfo 这个方法,需要根据用户名来获取用户所属的权限和角色。
package com.yellowcong.shiro.realm;
import java.util.Set;
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.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
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 org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.yellowcong.service.RolePermissionService;
import com.yellowcong.service.UserRoleService;
import com.yellowcong.service.UserService;
import com.yellowcong.shiro.model.User;
/**
* 创建日期:2017年9月23日 <br/>
* 创建用户:yellowcong <br/>
* 功能描述:用于授权操作
*/
public class SampleRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private UserRoleService userRoleService;
@Autowired
private RolePermissionService rolePermissionService;
/**
* 用户授权,当用户访问需要有权限的页面的情况,需要访问这个方法来获取权限列表
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection paramPrincipalCollection) {
//用户名称
Object username = paramPrincipalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 根据用户ID查询角色(role),放入到Authorization里。
Set<String> roles = userRoleService.getRoleByName(username.toString());
info.setRoles(roles);
// 根据用户ID查询权限(permission),放入到Authorization里。
Set<String> permissions = this.rolePermissionService.getPermissionByRole(roles);
info.setStringPermissions(permissions);
return info;
}
/**
* 认证,用户登录
* 登陆的时候,会调用这个
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken paramAuthenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) paramAuthenticationToken;
//数据库中,查询用户的信息
User user = userService.login(token.getUsername());
// token返回的是一个数组,将char类型转化为String类型
//这个是web前台传递过来的值
//这个密码的比对是通过Shiro自己给我们完成的
//密码是通过AuthenticatingRealm.getCredentialsMatcher 的方式来进行比对的
String pswDate = new String(token.getPassword());
//当用户为空的情况
if(user == null){
// 当没有用户的时候,抛出异常
throw new UnknownAccountException();
}
//第一个参数:用户名/用户对象
String username =token.getUsername();
//第二个参数:用户的密码
String password = user.getPassword();
//第三个参数:盐值(这个盐是 username)
ByteSource solt = null;
//第四个参数:获取这个Realm的信息
String realmName =this.getName();
//他们拿到密码web的密码,同数据库获取到的密码进行比对操作
return new SimpleAuthenticationInfo(username, password, solt,realmName);
}
}
权限控制
1、基于代码实现权限管理
Subject currentUser = SecurityUtils.getSubject();
if (currentUser.hasRole("administrator")) {
//拥有角色administrator
} else {
//没有角色处理
}
2、jsp端,权限的处理
通过jsp的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> | 默认显示用户名称 |
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%--shiro 标签 --%>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>后台管理 - yellowcong</title>
<script src="<%=request.getContextPath() %>/resources/plugins/jquery/jquery.min.js"></script>
</head>
<body class="layui-layout-body" >
<shiro:hasRole name="admin">
<a href="<%=request.getContextPath() %>/user/admin">管理员</a><br/>
</shiro:hasRole>
<shiro:hasRole name="user">
<a href="<%=request.getContextPath() %>/user/user">普通用户</a><br/>
</shiro:hasRole>
<a href="<%=request.getContextPath() %>/user/loginOut">退出</a>
</body>
</html>
普通用户登录
管理员用户登录
3、基于注解的方式
注解 | 意义 | 案例 |
---|---|---|
@RequiresAuthentication | 验证用户是否登录 | |
@RequiresUser | 当前用户已经验证过了或则记住我了 | |
@RequiresGuest | 是否是游客身份 | |
@RequiresRoles | 判断subject中有aRoleName角色才可以访问方法someMethod | @RequiresRoles({“admin”}) |
@RequiresPermissions | 需要拥有权限 | @RequiresPermissions({“file:read”, “write:aFile.txt”} ) |
案例
控制层
//只有管理员,才能执行这个方法
@RequestMapping("/admin/test")
public String adminTest(){
shiroService.test();
return "user/admin_test";
}
只能在 service 层添加权限的注解 如果放到Controller层,就不生效。
package com.yellowcong.service;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.stereotype.Service;
/**
* 创建日期:2017/12/20<br/>
* 创建时间:17:21:33<br/>
* 创建用户:yellowcong<br/>
* 机能概要:
*/
@Service("shiroService")
public class ShiroService {
@RequiresRoles({"admin"})
public void test() {
System.out.println("执行了程序");
}
}
普通用户访问
管理人员正常执行
@RequiresRoles({“admin”})不生效的问题
1、注解需要写在Service层
会遇到打死都不执行注解的问题,后来发现,如果把Shiro的注解写在SpringMvc的Controller层就不好用,需要写在Service层
2、需要将shiro生命周期配置在Spring-mvc.xml的配置文件中
<!-- Shiro生命周期处理器-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- AOP式方法级权限检查 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>