如果未通过身份验证,Quarkus 会提供重定向 url

Quarkus provide redirect url if not authenticated

我正在建立一个网络ui,并决定通过 cookie 中的 jwt 获得授权。

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

我设置网络的代码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();
    }
}

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

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

实际的响应处理取决于客户端是什么:如果是浏览器,那么您可能想要 return 303302 重定向响应 location header 包含您的登录 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();
    }
}

另一种选择是,您在端点内以编程方式处理身份验证,检查 Principal 或当前 JWTToken 所需的属性,如果不够,return 相应的 Response 例如return Response.seeOther("/login").

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