Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用RESTEasy显示用于基本身份验证的浏览器登录表单_Java_Jax Rs_Basic Authentication_Resteasy - Fatal编程技术网

Java 如何使用RESTEasy显示用于基本身份验证的浏览器登录表单

Java 如何使用RESTEasy显示用于基本身份验证的浏览器登录表单,java,jax-rs,basic-authentication,resteasy,Java,Jax Rs,Basic Authentication,Resteasy,我目前正在使用JAX-RS,特别是Resteasy,因为它“只适用于”Wildfly,我不需要配置任何东西。这是我使用它的唯一原因 我已经实现了基本身份验证,希望稍后用OAuth2替换它,只是为了简单起见,现在就这么做了 ContainerRequestFilter如下所示 @Provider public class SecurityFilter implements ContainerRequestFilter { private static final Stri

我目前正在使用JAX-RS,特别是Resteasy,因为它“只适用于”Wildfly,我不需要配置任何东西。这是我使用它的唯一原因

我已经实现了基本身份验证,希望稍后用OAuth2替换它,只是为了简单起见,现在就这么做了

ContainerRequestFilter如下所示

    @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();
    }
}
@Provider
公共类SecurityFilter实现ContainerRequestFilter{
私有静态最终字符串授权\u头\u KEY=“授权”;
私有静态最终字符串授权\u头\u前缀=“基本”;
@凌驾
公共无效筛选器(ContainerRequestContext ContainerRequestContext)引发IOException{
如果(已验证(containerRequestContext)==false)
containerRequestContext.abortWith(createUnauthorizedResponse(“拒绝访问”);
}
私有布尔值已验证(ContainerRequestContext ContainerRequestContext){
List authHeader=containerRequestContext.getHeaders().get(授权\头\密钥);
ResourceMethodInvoker methodInvoker=(ResourceMethodInvoker)containerRequestContext.getProperty(“org.jboss.resteasy.core.ResourceMethodInvoker”);
Method=methodInvoker.getMethod();
RolesAllowed rolesAnnotation=method.getAnnotation(RolesAllowed.class);
if(authHeader!=null&&authHeader.size()>0){
字符串authToken=authHeader.get(0).replaceFirst(授权\头\前缀“”);
字节[]已解码=空;
试一试{
decoded=Base64.getDecoder().decode(authToken);
}捕获(IllegalArgumentException ex){
返回false;
}
字符串解码字符串=新字符串(已解码);
StringTokenizer tokenizer=新的StringTokenizer(decodedString,“:”);
字符串username=null,password=null;
if(tokenizer.countTokens()<2)
返回false;
username=tokenizer.nextToken();
password=tokenizer.nextToken();
if(DbController.isValid(用户名、密码、角色说明.value()))
返回true;
}
返回false;
}
私有响应createUnauthorizedResponse(字符串消息){
返回Response.status(Response.status.UNAUTHORIZED)
.entity(“{\'未经授权\\:\”+msg+“\”}”)
.type(MediaType.APPLICATION_JSON)
.build();
}
}
这对邮递员很管用。我也意识到这些API的主要用途是在其他程序中

但如果在浏览器中打开,它会要求您输入您的凭据,而不是仅仅告诉您未经授权,无法真正输入凭据,这将是一件好事。除非你做了一些诡计,手动将它放在标题中,但是你也可以使用postman

如果我使用auth constraint角色admin设置一个安全约束,它确实会给出一个登录对话框,但是授权不起作用,它只是不断请求授权

除了containerRequestContext.abortWith,还有什么我可以做的吗?或者我需要使用一种完全不同的方法,但它不能用于ContainerRequestFilter?

您需要将标题添加到中止的响应中。此标题告诉浏览器它应该显示默认的浏览器登录表单

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上的登录名