背景
Spring Security + JWT を使ってログイン認証処理を実装中に、トークンに userId を含める構成に変更したところ、 「Long cannot be converted to Integer」 などのエラーが続出して泥沼に…。
その時の自分用備忘録兼、同じことで詰まりそうな人の助けになればと思い、まとめておきます。
JWTトークンに userId を含めるように変更
以前はトークンに username を埋め込んでいたけど、ユーザー名変更時に認証が崩れるので、userId を使うよう変更しました。名前でユーザー認証してる人はあんまりいないかもしれませんが…。サンプルがそうだったのでそうしちゃいました笑
皆さん、ユーザー認証に使うものは一意のものがいいですよ...
public String generateToken(Users user) {
return Jwts.builder()
.setSubject(String.valueOf(user.getId()))
.claim("username", user.getUsername()) // 任意
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1時間
.signWith(SECRET_KEY)
.compact();
}
JWT認証フィルターの修正
JwtAuthenticationFilter.java 内でも username ではなく userId を使うように変更
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && jwtUtil.validateToken(token.replace("Bearer ", ""))) {
String tokenValue = token.replace("Bearer ", "");
String userIdStr = jwtUtil.extractUserId(tokenValue);
Long userId = Long.parseLong(userIdStr);
UserDetails userDetails = myUserDetailsService.loadUserById(userId);
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);
}
filterChain.doFilter(request, response);
}
リポジトリのID型を Long に変えたことで、既存コードが次々コンパイルエラー。
java.lang.Integer cannot be converted to java.lang.Long
解決のためにやったこと
1.UsersRepository の ID型を Long に統一
public interface UsersRepository extends JpaRepository<Users, Long>
2.呼び出し側で .longValue() を付ける or 変数型を Long に変更
Integer userId = 123;
usersRepository.findById(userId.longValue()); // 明示的に変換
3.可能な限り全体的に ID 型を Long に揃える(引数やフィールド)
public Comments postComments(String content, Long userId, Long threadId, ... )
まとめ
・Integer ↔ Long は暗黙変換されない(longリテラル使うか .longValue() 必須)
・.longValue() は Integer → long に変換する標準メソッド
・ID系の型はプロジェクト初期から Long に統一しておいた方がいい(マジ後で泣くていうか最初に教えてくれればよかったのに…。セキュリティ付けようとか考えてるアプリ製作者は絶対にId刑の型はLong!!!Intengerはダメ!!!)