如何为Java Play Framework应用添加JWT认证
在Java Play Framework中添加JWT认证的实操步骤
针对你的员工信息API安全需求,下面是一套落地性强的JWT集成方案,都是项目里常用的做法:
1. 先加依赖
在项目的build.sbt里添加JJWT库的依赖——这是Java生态里用得最多的JWT工具:
libraryDependencies += "io.jsonwebtoken" % "jjwt-api" % "0.11.5" libraryDependencies += "io.jsonwebtoken" % "jjwt-impl" % "0.11.5" % Runtime libraryDependencies += "io.jsonwebtoken" % "jjwt-jackson" % "0.11.5" % Runtime
2. 写个JWT工具类
封装Token的生成和验证逻辑,避免重复代码:
import io.jsonwebtoken.*; import io.jsonwebtoken.security.Keys; import javax.crypto.SecretKey; import java.util.Date; public class JwtUtil { // 密钥要够长(至少32位),别硬编码!建议从application.conf里读 private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor("your-32-char-plus-strong-secret-key".getBytes()); // Token有效期设为1小时,按需调整 private static final long EXPIRATION_TIME = 3600000; // 生成Token,传入用户名作为唯一标识 public static String generateToken(String username) { return Jwts.builder() .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SECRET_KEY, SignatureAlgorithm.HS256) .compact(); } // 从Token里提取用户名 public static String extractUsername(String token) { return Jwts.parserBuilder() .setSigningKey(SECRET_KEY) .build() .parseClaimsJws(token) .getBody() .getSubject(); } // 验证Token是否有效 public static boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { return false; } } }
3. 做个登录接口
先实现用户登录,验证凭证后返回Token:
import play.mvc.Controller; import play.mvc.Result; import play.mvc.Http; import com.fasterxml.jackson.databind.JsonNode; import play.libs.Json; public class AuthController extends Controller { // 这里模拟用户验证,实际要对接数据库查账号密码 private boolean validateUser(String username, String password) { return "admin".equals(username) && "your-password".equals(password); } public Result login(Http.Request request) { JsonNode json = request.body().asJson(); if (json == null) { return badRequest("缺少JSON请求体"); } String username = json.get("username").asText(); String password = json.get("password").asText(); if (validateUser(username, password)) { String token = JwtUtil.generateToken(username); return ok(Json.toJson(new TokenResponse(token))); } else { return unauthorized("账号或密码错误"); } } // 返回Token的DTO类 public static class TokenResponse { public String token; public TokenResponse(String token) { this.token = token; } } }
4. 写JWT认证过滤器
用Action拦截需要保护的API,自动验证Token:
import play.mvc.Action; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; // 自定义注解,标记需要认证的接口 @With(JwtAuthAction.class) public @interface JwtAuth {} public class JwtAuthAction extends Action<JwtAuth> { @Override public CompletionStage<Result> call(Http.Request request) { // 从请求头拿Token,格式是Bearer <token> String authHeader = request.header("Authorization").orElse(null); if (authHeader == null || !authHeader.startsWith("Bearer ")) { return CompletableFuture.completedStage(unauthorized("缺少或无效的Authorization请求头")); } String token = authHeader.substring(7); if (JwtUtil.validateToken(token)) { // 把用户名存到请求属性里,后续接口能直接用 String username = JwtUtil.extractUsername(token); Http.Request updatedRequest = request.addAttr(UsernameKey.USERNAME, username); return delegate.call(updatedRequest); } else { return CompletableFuture.completedStage(unauthorized("无效的JWT Token")); } } // 定义请求属性的Key,方便后续获取用户名 public static class UsernameKey { public static final Http.RequestAttrAccessor<String> USERNAME = Http.RequestAttrAccessor.create(); } }
5. 配置路由
在routes文件里配置登录接口和受保护的员工API:
POST /login controllers.AuthController.login(request: Request) GET /employees controllers.EmployeeController.getAllEmployees(request: Request) @JwtAuth GET /employees/:id controllers.EmployeeController.getEmployeeById(id: Long, request: Request) @JwtAuth
6. 员工API里用认证信息
在你的员工控制器中,可以获取当前登录的用户名,做权限控制或业务逻辑:
import play.mvc.Controller; import play.mvc.Result; import play.mvc.Http; public class EmployeeController extends Controller { public Result getAllEmployees(Http.Request request) { String username = request.attrs().get(JwtAuthAction.UsernameKey.USERNAME); // 这里写你的员工信息查询逻辑,比如根据用户名过滤数据 return ok("当前登录用户:" + username + ",员工列表数据"); } }
几个关键注意点
- 密钥别硬编码:把密钥放到
application.conf里,用play.Configuration读取,比如config.getString("jwt.secret")。 - 用HTTPS:生产环境一定要用HTTPS传输Token,防止被中间人窃取。
- 支持刷新Token:如果Token有效期短,可以实现刷新Token接口,避免用户频繁登录。
- 扩展权限控制:可以在JWT的Claims里加用户角色,在过滤器里验证角色权限。
内容的提问来源于stack exchange,提问作者Siddarth K
相关产品推荐
相关产品推荐

