目次
認可された
ユーザーがログインした後、ユーザーが指定されたロールの指定された権限を持っているかどうかを確認する必要があります。シロは判断のための便利なツールも提供します。このツールはRealmの判定用doGetAuthorizationInfoメソッドです。
許可判定を引き起こす方法は2つあります
(1) ページ内の hiro:**** 属性から判断
(2) インターフェースサービスの @Requires**** アノテーションにより判定
バックエンド インターフェイス サービス アノテーション
認可検証は、インターフェイス サービス メソッドにアノテーションを追加することで実現できます。アノテーションは、コントローラー メソッドまたはビジネス メソッドに追加でき、通常はコントローラー メソッドに追加されます。一般的に使用されるアノテーションは次のとおりです。
(1)@認証が必要です
ユーザーがログインしているかどうかを確認します。メソッド subject.isAuthenticated() と同等です。
(2)@RequiresUser
ユーザーが記憶されているかどうかを確認します。ログイン認証が成功した場合は、subject.isAuthenticated() が true になります。ログイン後は、subject.isRemembered() が true になります。
(3)@RequiresGuest
ゲストのリクエストであるか、訪問者のリクエストであるかを確認し、現時点では subject.getPrincipal() が null であることを確認します。
(4)@RequiresRoles
サブジェクトに対応するロールがあることを確認し、ロールのアクセス メソッドがある場合は、例外 AuthorizationException がスローされます。例えば:
@RequiresRoles(“aRoleName”)
void someMethod();
サブジェクトのみがメソッド someMethod() にアクセスするための aRoleName ロールを持っています
(5)@RequiresPermissions
サブジェクトに対応する権限があり、権限がある場合はアクセス メソッドがあることを確認します。権限がない場合は、例外 AuthorizationException がスローされます。例えば:
@RequiresPermissions (「ファイル:読み取り」、「書き込み:aFile.txt」)
void someMethod();
メソッド someMethod() にアクセスするには、サブジェクトには file:read と write:aFile.txt の両方のアクセス許可が必要です。
認可の検証 - ロールアクセスなし
(1) コントローラメソッドの追加と検証ロールアノテーションの追加
//登录认证验证角色
@RequiresRoles("admin")
@GetMapping("userLoginRoles")
@ResponseBody
public String userLoginRoles() {
System.out.println("登录认证验证角色");
return "验证角色成功";
}
(2) main.htmlを修正する
<body>
<h1>Shiro 登录认证后主页面</h1>
<br>
登录用户为:<span th:text="${session.user}"></span>
<br>
<a href="/logout">登出</a>
<br>
<a href="/myController/userLoginRoles">测试授权</a>
</body>
(3) MyRealmメソッドを変更する
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比
@Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入自定义授权方法");
return null;
}
(4) テストを実行する
認可の検証 - 検証用のロールを取得します
(1) MyRealmメソッドを変更する
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比
@Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入自定义授权方法");
//1 创建对象,存储当前登录的用户的权限和角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//2 存储角色
info.addRole("admin");
//返回
return info;
}
(2) テストを実行する
(3) ライブラリテーブルの確認
CREATE TABLE `role` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` VARCHAR(30) DEFAULT NULL COMMENT '角色名',
`desc` VARCHAR(50) DEFAULT NULL COMMENT '描述',
`realname` VARCHAR(20) DEFAULT NULL COMMENT '角色显示名',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色表';
CREATE TABLE `role_user` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`uid` BIGINT(20) DEFAULT NULL COMMENT '用户 id',
`rid` BIGINT(20) DEFAULT NULL COMMENT '角色 id',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色用户映射表';
(4) SQL を実行して、ユーザー名に応じて対応するロール情報をクエリします。
SELECT NAME FROM role WHERE id IN (SELECT Rid FROM role_user WHERE uid=(SELECT id FROM USER WHERE NAME='张三'));
(5) マッパーメソッド
@Repository
public interface UserMapper extends BaseMapper<User> {
@Select("SELECT NAME FROM role WHERE id IN (SELECT rid FROM
role_user WHERE uid=(SELECT id FROM USER WHERE NAME=#{principal}))")
List<String> getUserRoleInfoMapper(@Param("principal") String
principal);
}
(6)サービスの実現
//获取用户的角色信息
@Override
public List<String> getUserRoleInfo(String principal) {
return userMapper.getUserRoleInfoMapper(principal);
}
(7) MyRealmメソッドの修正
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比
@Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入自定义授权方法");
//获取当前用户身份信息
String principal =
principalCollection.getPrimaryPrincipal().toString();
//调用接口方法获取用户的角色信息
List<String> roles = userService.getUserRoleInfo(principal);
System.out.println("当前用户角色信息:"+roles);
//创建对象,存储当前登录的用户的权限和角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//存储角色
info.addRoles(roles);
//返回
return info;
}
(8) ログインテストを開始する
認可の検証 - 検証のための許可を取得します。
権限の検証の取得は、ロールの取得と似ています
(1) ライブラリテーブルを確認する
CREATE TABLE `permissions` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` VARCHAR(30) DEFAULT NULL COMMENT '权限名',
`info` VARCHAR(30) DEFAULT NULL COMMENT '权限信息',
`desc` VARCHAR(50) DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='权限表';
CREATE TABLE `role_ps` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`rid` BIGINT(20) DEFAULT NULL COMMENT '角色 id',
`pid` BIGINT(20) DEFAULT NULL COMMENT '权限 id',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色权限映射表`
(2) SQLをクエリして、ロール名に応じて対応する権限情報をクエリします。
SELECT info FROM 権限 WHERE id IN (SELECT pid FROM role_ps WHERE Rid IN (SELECT id FROM role WHERE NAME IN('admin','userMag')));
(3)マッパーメソッド
@Select({
"<script>",
"select info FROM permissions WHERE id IN ",
"(SELECT pid FROM role_ps WHERE rid IN (",
"SELECT id FROM role WHERE NAME IN ",
"<foreach collection='roles' item='name' open='('
separator=',' close=')'>",
"#{name}",
"</foreach>",
"))",
"</script>"
})
List<String> getUserPermissionInfoMapper(@Param("roles")List<String>
roles);
(4)サービスの実現
//获取用户角色的权限信息
@Override
public List<String> getUserPermissionInfo(List<String> roles) {
return userMapper.getUserPermissionInfoMapper(roles);
}
(5) MyRealmメソッドの修正
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比
@Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入自定义授权方法");
//获取当前用户身份信息
String principal =
principalCollection.getPrimaryPrincipal().toString();
//调用接口方法获取用户的角色信息
List<String> roles = userService.getUserRoleInfo(principal);
System.out.println("当前用户角色信息:"+roles);
//调用接口方法获取用户角色的权限信息
List<String> permissions =
userService.getUserPermissionInfo(roles);
System.out.println("当前用户权限信息:"+permissions);
//创建对象,存储当前登录的用户的权限和角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//存储角色
info.addRoles(roles);
//存储权限信息
info.addStringPermissions(permissions);
//返回
return info;
}
(6) コントローラーメソッドの追加
//登录认证验证权限
@RequiresPermissions("user:delete")
@GetMapping("userPermissions")
@ResponseBody
public String userLoginPermissions() {
System.out.println("登录认证验证权限");
return "验证权限成功";
}
(7) main.htmlを変形する
<body>
<h1>Shiro 登录认证后主页面</h1>
<br>
登录用户为:<span th:text="${session.user}"></span>
<br>
<a href="/logout">登出</a>
<br>
<a href="/myController/userLoginRoles">测试授权-角色验证</a>
<br>
<a href="/myController/userPermissions">测试授权-权限验证</a>
</body>
(8) ログインテストを開始する
認可の検証 - 例外処理
(1) 認証例外処理クラスを作成し、@ControllerAdvice と @ExceptionHandler を使用して特殊な例外処理を実装します。
@ControllerAdvice
public class PermissionsException {
@ResponseBody
@ExceptionHandler(UnauthorizedException.class)
public String unauthorizedException(Exception ex){
return "无权限";
}
@ResponseBody
@ExceptionHandler(AuthorizationException.class)
public String authorizationException(Exception ex){
return "权限认证失败";
}