0

我正在构建一个 web ui,并决定通过 jwt 在 cookie 中获取身份验证。

我已经得到了最低限度的工作,但是当我在角色后面保留一个页面时,该页面(可以预见)不会加载。与其不加载,我更希望能够告诉端点重定向到实际的登录页面。这可能吗?理想情况下,我将能够在端点上提供注释以说“如果未经过身份验证,请转到此处”。

我设置 web ui 端点的代码:

@Traced
@Slf4j
@Path("/")
@Tags({@Tag(name = "UI")})
@RequestScoped
@Produces(MediaType.TEXT_HTML)
public class Index extends UiProvider {

    @Inject
    @Location("webui/pages/index")
    Template index;
    @Inject
    @Location("webui/pages/overview")
    Template overview;

    @Inject
    UserService userService;

    @Inject
    JsonWebToken jwt;

    @GET
    @PermitAll
    @Produces(MediaType.TEXT_HTML)
    public TemplateInstance index(
            @Context SecurityContext securityContext
    ) {
        logRequestContext(jwt, securityContext);
        return index.instance();
    }

    @GET
    @Path("overview")
    @RolesAllowed("user")
    @Produces(MediaType.TEXT_HTML)
    public TemplateInstance overview(
            @Context SecurityContext securityContext
    ) {
        logRequestContext(jwt, securityContext);
        return overview.instance();
    }
}
4

1 回答 1

1

这取决于您希望如何处理安全性和导航。如果您使用声明性 RBAC( @RolesAllowed),则只能通过 JAXRS ExceptionMapper控制响应。您需要知道当用户无权访问所需资源时引发的异常;例如,如果用户有有效的令牌但不满足约束,那么如果他没有通过有效的凭据,那么@RolesAllowed它将是。io.quarkus.security.ForbiddenExceptionio.quarkus.security.UnauthorizedException

当您知道异常时,您可以定义您的 ExceptionMapper(确保设置正确的优先级,@Priority因为类路径上可能还有其他异常映射器,例如 Quarkus 在开发模式下提供的那些)。

实际的响应处理取决于客户端是什么:如果是浏览器,那么您可能希望返回303302重定向响应,其中location包含您的登录 URL 的标头,以便将原始请求重定向到登录。一个例子UnauthorizedException

import io.quarkus.security.UnauthorizedException;

import javax.annotation.Priority;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider//register it as jaxrs provider
@Priority(1)//lower number-higher prio
//exception mappers are selected on best match for the exception class
//so make sure you find the particular exception you want to map
public class MyUnauthorizedExceptionMapper implements ExceptionMapper<UnauthorizedException> { 
    @Context//you can inject JAXRS contextual resources here
    UriInfo crc;

    @Override
    public Response toResponse(UnauthorizedException exception) {
        System.out.println("User not authorized to access: " + crc.getRequestUri());
        return Response //seeOther = 303 redirect
                .seeOther(UriBuilder.fromUri("/someLogin")
                        //common pattern is to pass the original URL as param,
                        //so that after successful login, you redirect user back where he wanted
                        .queryParam("returnUrl", crc.getRequestUri())
                        .build())//build the URL where you want to redirect
                .entity("Not authorized")//entity is not required
                .build();
    }
}

其他选择是,您在端点内以编程方式处理身份验证,检查所需属性的Principalor current JWTToken,如果不够,则返回相应的Responseeg return Response.seeOther("/login")

这应该可以,但如果您的客户端是一些 javascript 代码,执行 POST 请求,则可能会导致问题。一般来说,您最好从专用服务器提供您的 UI,使用 Quarkus 作为 API 端点提供者,通过 HTTP/REST 在您的 UI 和 BE 之间进行通信。这样你就可以更好地控制行为。

于 2021-11-15T17:59:09.167 回答