You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 02:58:22