如何使用RESTEasy显示用于基本身份验证的浏览器登录表单 [英] How to show browser login form for basic authentication using RESTEasy

查看:186
本文介绍了如何使用RESTEasy显示用于基本身份验证的浏览器登录表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在搞混JAX-RS,特别是Resteasy,因为它可以与Wildfly兼容",而我无需进行任何配置.那真的是我使用它的唯一原因.

I´m currently messing around with JAX-RS specifically Resteasy, because it "just works" with Wildfly and I don´t have to configure anything. That´s really the only reason I use that.

我已经实现了基本身份验证,希望以后再用OAuth2进行替换,出于简单起见,现在才进行此操作.

I did already implement Basic Authentication, looking forward to replacing it with OAuth2 later, just did this now for simplicity reasons.

ContainerRequestFilter看起来像这样

The ContainerRequestFilter looks like this

    @Provider
    public class SecurityFilter implements ContainerRequestFilter {

    private static final String AUTHORIZATION_HEADER_KEY = "Authorization";
    private static final String AUTHORIZATION_HEADER_PREFIX = "Basic ";

    @Override
    public void filter(ContainerRequestContext containerRequestContext) throws IOException {

        if(isAuthenticated(containerRequestContext) == false)
            containerRequestContext.abortWith(createUnauthorizedResponse("Access denied."));
    }

    private boolean isAuthenticated(ContainerRequestContext containerRequestContext) {
        List<String> authHeader = containerRequestContext.getHeaders().get(AUTHORIZATION_HEADER_KEY);

        ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) containerRequestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
        Method method = methodInvoker.getMethod();
        RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);

        if (authHeader != null && authHeader.size() > 0) {
            String authToken = authHeader.get(0).replaceFirst(AUTHORIZATION_HEADER_PREFIX, "");

            byte[] decoded = null;

            try {
                decoded = Base64.getDecoder().decode(authToken);
            } catch (IllegalArgumentException ex) {
                return false;
            }

            String decodedString = new String(decoded);
            StringTokenizer tokenizer = new StringTokenizer(decodedString, ":");

            String username = null, password = null;

            if(tokenizer.countTokens() < 2)
                return false;

            username = tokenizer.nextToken();
            password = tokenizer.nextToken();

            if (DbController.isValid(username, password, rolesAnnotation.value()))
                return true;
        }

        return false;
    }

    private Response createUnauthorizedResponse(String msg) {
        return Response.status(Response.Status.UNAUTHORIZED)
                .entity("{ \"Unauthorized\" : \"" + msg + "\" }")
                .type(MediaType.APPLICATION_JSON)
                .build();
    }
}

与邮递员一起很好地工作.而且我确实意识到此类api的主要用法是在其他程序中.

It works fine with postman. And I do realize that the main usage of such apis is in well other programs.

但这很好,如果在浏览器中打开它,它会要求您输入凭据,而不仅仅是告诉您您没有授权,而无法真正输入凭据.除非您花了点时间手动将其放在标题中,否则您最好还是使用邮递员.

But it would be nice, if opened in a browser it would ask you to enter your credentials, instead of just telling you that you are not authorized, with no way to really enter your credentials. Unless you do some trickery to manually put it in the header, but then you might as well just use postman.

如果我使用auth-constraint角色admin设置了安全约束,它会显示一个登录对话框,但是授权不起作用,它只会继续要求授权.

If I put a security constraint with auth-constraint role admin it does give a login dialog, but then the authorization does not work and it just keeps asking for authorization.

除了containerRequestContext.abortWith之外,还有其他什么可以做的吗?还是我需要使用一种完全不同的方法,并且它不能与ContainerRequestFilter一起使用?

Is there anything else that I can do instead of containerRequestContext.abortWith? Or do I need to use a completely different approach and it just won´t work with ContainerRequestFilter?

推荐答案

您需要添加

You need to add the WWW-Authenticate header to the response that you abort with. This header tells the browser that it should present the default browser login form.

private static final String CHALLENGE_FORMAT = "%s realm=\"%s\"";

private Response createUnauthorizedResponse() {
    return Response.status(Response.Status.UNAUTHORIZED)
            .header(HttpHeaders.WWW_AUTHENTICATE, String.format(CHALLENGE_FORMAT, "Basic", "Access"))
            .type(MediaType.TEXT_PLAIN_TYPE)
            .entity("Credentials are required to access this resource.")
            .build();

这是Chrome上的登录外观

And here's what the login should look like on Chrome

这篇关于如何使用RESTEasy显示用于基本身份验证的浏览器登录表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆