Play Framework 2.8.x:过滤器中检查用户角色并拒绝请求方法
解决Play Framework 2.8.x过滤器中权限检查与请求拒绝问题
嘿,我来帮你搞定这个权限过滤的需求!针对你的两个问题,我一步步给你说明:
1. 如何在过滤器中返回指定状态码拒绝请求
Play Framework里的Result类提供了各种现成的状态码方法,比如forbidden()(403禁止访问)、unauthorized()(401未授权)等。你不需要调用next.apply(rh),直接用CompletableFuture.completedFuture()包装对应的Result就能返回拒绝响应了。
比如要返回403禁止访问的示例:
@Override public CompletionStage<Result> apply(Function<Http.RequestHeader, CompletionStage<Result>> next, Http.RequestHeader rh) { // 先执行权限检查逻辑,不符合就直接返回拒绝结果 if (!hasPermission(rh)) { // 返回403状态码,还可以自定义响应提示文本 return CompletableFuture.completedFuture(Results.forbidden("抱歉,你没有该页面的访问权限")); } // 有权限就继续处理后续请求 return next.apply(rh); }
常用状态码对应方法:
- 401未授权:
Results.unauthorized() - 403禁止访问:
Results.forbidden() - 404页面不存在:
Results.notFound()
2. 如何在过滤器中检查用户角色
要检查用户角色,首先得从请求中获取当前登录用户的信息,具体方式取决于你项目的认证机制,这里给你两种常见场景的实现:
场景一:使用Play内置Security认证
如果你用了Play的Security.Authenticator,可以通过请求属性直接获取认证后的用户:
private boolean hasPermission(Http.RequestHeader rh) { // 获取当前认证用户,未登录则直接返回false Optional<User> currentUser = rh.attrs().getOptional(Security.AuthenticatedUser.class); if (currentUser.isEmpty()) { return false; } User user = currentUser.get(); // 检查用户角色,这里假设User类有getRoles()方法返回角色列表 // 可以根据请求路径做精细化权限判断 return switch (rh.path()) { case "/admin/dashboard" -> user.getRoles().contains("ADMIN"); case "/user/profile" -> user.getRoles().contains("USER"); default -> true; // 其他页面默认允许访问 }; }
场景二:自定义Session存储用户信息
如果你的用户ID存在Session里,需要从数据库查询角色信息,可以这样做:
// 假设你有一个UserService用来查询用户信息 @Inject private UserService userService; private boolean hasPermission(Http.RequestHeader rh) { // 从Session中获取用户ID Optional<String> userIdOpt = rh.session().get("userId"); if (userIdOpt.isEmpty()) { return false; } // 从数据库查询用户详情 User user = userService.findById(userIdOpt.get()); if (user == null) { return false; } // 角色检查逻辑和上方一致 return switch (rh.path()) { case "/admin/dashboard" -> user.getRoles().contains("ADMIN"); case "/user/profile" -> user.getRoles().contains("USER"); default -> true; }; }
完整过滤器示例代码
把上面的逻辑整合到你的PageAccessFilter里,最终代码大概是这样(注意处理异步IO场景):
import play.mvc.*; import play.libs.concurrent.HttpExecutionContext; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.Optional; import javax.inject.Inject; public class PageAccessFilter extends Filter { private final UserService userService; private final HttpExecutionContext ec; @Inject public PageAccessFilter(Materializer mat, UserService userService, HttpExecutionContext ec) { super(mat); this.userService = userService; this.ec = ec; } @Override public CompletionStage<Result> apply(Function<Http.RequestHeader, CompletionStage<Result>> next, Http.RequestHeader rh) { // 先排除不需要权限检查的路径,比如登录页、静态资源 if (isPublicPath(rh.path())) { return next.apply(rh); } // 异步执行权限检查(涉及数据库查询时,要用HttpExecutionContext确保线程安全) return CompletableFuture.supplyAsync(() -> hasPermission(rh), ec.current()) .thenApply(hasPerm -> { if (!hasPerm) { return Results.forbidden("抱歉,你没有该页面的访问权限"); } return null; }) .thenCompose(result -> { if (result != null) { return CompletableFuture.completedFuture(result); } return next.apply(rh); }); } private boolean isPublicPath(String path) { return path.startsWith("/login") || path.startsWith("/assets/") || path.equals("/"); } private boolean hasPermission(Http.RequestHeader rh) { Optional<String> userIdOpt = rh.session().get("userId"); if (userIdOpt.isEmpty()) { return false; } User user = userService.findById(userIdOpt.get()); if (user == null) { return false; } return switch (rh.path()) { case "/admin/dashboard" -> user.getRoles().contains("ADMIN"); case "/user/profile" -> user.getRoles().contains("USER"); default -> true; }; } }
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

