Javaコード監査:Shiro認証・認可メカニズム

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("データ作成成功");
  }
}

タグ: Java Shiro JWT 認証 認可

8月1日 16:37 投稿