Shiroの主要コンポーネント
Shiroの権限管理モデルはユーザー、ロール、権限で構成されます。主要な構成要素は以下の通りです:
- AuthenticationToken: ユーザー認証情報をカプセル化
- SecurityManager: 認証・認可の中核機能
- Subject: ユーザープリンシパルを抽象化
- Realm: 認証・認可ロジックのカスタム実装
- AuthenticationInfo: ユーザー役割情報
- AuthorizationInfo: ユーザー権限情報
Shiro設定の実装
Realm実装ではAuthorizingRealmを継承し、以下のメソッドを実装します:
public class CustomRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) {
String username = (String) token.getPrincipal();
String correctPassword = userService.getPassword(username);
return new SimpleAuthenticationInfo(username, correctPassword, getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
Set<String> roles = roleService.getRoles(username);
Set<String> permissions = permService.getPermissions(username);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roles);
info.setStringPermissions(permissions);
return info;
}
}
JWT連携の実装
JWT認証ではCredentialsMatcherをカスタマイズします:
public class JwtValidator implements CredentialsMatcher {
@Override
public boolean validateCredentials(
AuthenticationToken token,
AuthenticationInfo info) {
return true; // JWTは事前検証済み
}
}
トークン検証ロジックの実装例:
private boolean validateJwtToken(String token, String userId) {
String storedToken = redisClient.get(CacheKey.USER_TOKEN + token);
if (StringUtils.isNotEmpty(storedToken)) {
if (!JwtUtils.verifySignature(storedToken, userId)) {
String newToken = JwtUtils.generateToken(userId);
redisClient.set(CacheKey.USER_TOKEN + token, newToken);
}
return true;
}
return false;
}
セキュリティマネージャ設定
@Bean
public SecurityManager securityManager(CustomRealm realm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(realm);
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
SessionStorageEvaluator evaluator = new SessionStorageEvaluator();
evaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(evaluator);
manager.setSubjectDAO(subjectDAO);
manager.setCacheManager(new RedisCacheManager());
return manager;
}
権限制御の実装
@RestController
@RequestMapping("/api/data")
public class DataController {
@PostMapping
@RequiresPermissions("data:create")
public Response createData(@RequestBody DataPayload payload) {
dataService.save(payload);
return Response.success("データ作成成功");
}
}