四 Shiro 鉴权
1 介绍
授权功能:就是为用户分配相关的权限的过程;鉴权功能:判断当前访问用户是否有某个资源的访问权限的过程。我们的权限管理系统是基于角色的权限管理,所以在系统中应该需要下面三个子模块:用户管理 2. 角色管理 3. 权限管理。我们所需要的就是将用户拥有的权限告知 Shiro,供其在权限校验的时候使用。
2 基于ini的鉴权
① 编写 ini 配置文件:shiro-author.ini
#用户的身份、凭据、角色
[users]
dahuang=888,hr,seller
xiaohuang=666,seller
#角色与权限信息,权限字符串也可以使用*通配符
[roles]
hr=user:list,user:delete
seller=customer:list,customer:save
② 测试
public class ShiroDemo {
@Test
public void testAuthorByIni(){
// 认证功能
DefaultSecurityManager securityManager = new DefaultSecurityManager();
IniRealm realm = new IniRealm("classpath:shiro-author.ini");
securityManager.setRealm(realm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("dahuang","888");
subject.login(token);
// 鉴权功能
System.out.println("查当前用户是否有customer:list权限:" + subject.isPermitted("customer:list"));
System.out.println("查当前用户是否有user:list权限:" + subject.isPermitted("user:list"));
//根据结果返回布尔数组一一对应查看有无权限
System.out.println("查当前用户是否有user:list,customer:list这两个权限:"
+ Arrays.toString(subject.isPermitted("user:list", "customer:list")));
//只要有一项权限没有就返回false
System.out.println("查当前用户是否有user:list,customer:list这两个权限:"
+ subject.isPermittedAll("user:list", "customer:list"));
System.out.println("-------------------------");
// 有权限正常运行,没权限抛异常,可进行捕获
//subject.checkPermission("user:list");
System.out.println("后续代码...");
System.out.println("===================================");
System.out.println("当前用户是否有seller角色:" + subject.hasRole("seller"));
System.out.println("当前用户是否有seller角色:" + subject.hasRole("hr"));
//有角色无反应,没有就报错
subject.checkRole("hr");
}
}
3 基于自定义Realm的鉴权
① 模拟数据库mapper
public class DataMapper {
//用户集合
private static Map<String, User> userData = new HashMap<String, User>();
//角色集合
private static Map<String, List<String>> roleData = new HashMap<String, List<String>>();
//权限集合
private static Map<String, List<String>> permissionData = new HashMap<String, List<String>>();
static{
//初始化用户数据
User u1 = new User("dahuang","666");
userData.put(u1.getUsername(),u1);
roleData.put(u1.getUsername(), Arrays.asList("seller"));
permissionData.put(u1.getUsername(),
Arrays.asList("customer:list","customer:save"));
User u2 = new User("xiaohuang","888");
userData.put(u2.getUsername(),u2);
roleData.put(u2.getUsername(), Arrays.asList("seller","hr"));
permissionData.put(u2.getUsername(),
Arrays.asList("customer:list","customer:save","user:list","user:delete"));
}
//提供静态方法,模拟数据库返回数据
public static User getUserByName(String username){
return userData.get(username);
}
public static List<String> getRoleByName(String username){
return roleData.get(username);
}
public static List<String> getPermissionByName(String username){
return permissionData.get(username);
}
}
② UserRealm 中为鉴权提供数据
// Realm是数据源 认证授权都只提供数据即可
public class UserRealm extends AuthorizingRealm {
// 授权功能
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 获取当前登录用户 登录后(user已在环境中)才进行授权 principals中含有一切信息
User user = (User) principals.getPrimaryPrincipal(); //获取在 doGetAuthenticationInfo 中存放在上下文中的对象
String username = user.getUsername();
// 当前登录用户的角色集合
List<String> roles = DataMapper.getRoleByName(username);
// 当前登录用户的权限集合
List<String> permissions = DataMapper.getPermissionByName(username);
// 需要将当前登录用户的权限和角色集合与返回的SimpleAuthorizationInfo 绑定关系
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roles);
info.addStringPermissions(permissions);
return info;
}
// 认证功能
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 如何获取数据? 返回当前用户名(map的key)
// String username = (String) token.getPrincipal();
// 此处使用它的子类获取token
UsernamePasswordToken token1 = (UsernamePasswordToken) token;
// 通过token获取用户名
String username = token1.getUsername();
// 根据用户名去mapper中查询数据
User user = DataMapper.getUserByName(username);
if(user == null){
return null;
}
// 需要返回一个 SimpleAuthenticationInfo 对象
// 3个参数 (需要存储到上下文环境中的对象(登录成功后向session中存对象),密码信息,盐,Realm名字(这是父类的方法))
return new SimpleAuthenticationInfo(user,user.getPassword(),
ByteSource.Util.bytes(user.getSalt()),getName());
}
}
③ 测试
public class ShiroDemo {
@Test
public void testAuthorByIniUserRealm(){
/*********************************** 认证功能 *************************************/
DefaultSecurityManager securityManager = new DefaultSecurityManager();
UserRealm realm = new UserRealm();
securityManager.setRealm(realm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("qg","666");
subject.login(token);
/*********************************** 认证功能 *************************************/
/*********************************** 鉴权功能 *************************************/
System.out.println("当前用户是否有customer:list权限:"
+ subject.isPermitted("customer:list"));
System.out.println("当前用户是否有user:list权限:"
+ subject.isPermitted("user:list"));
System.out.println("当前用户是否有user:list权限:"
+ subject.isPermitted("user:list"));
System.out.println("当前用户是否有seller角色:"
+ subject.hasRole("seller"));
System.out.println("当前用户是否有hr角色:"
+ subject.hasRole("hr"));
}
}