Play框架2.4的HTTP基本身份验证

Ole*_*leg 2 authentication scala playframework playframework-2.4

我正在寻找一种对我的Play框架应用进行身份验证的方法:我希望允许/禁止对未经身份验证的用户进行整体访问

是否有一些适用的模块/解决方案?我不需要任何形式的身份验证,只需要未经身份验证的用户的401 HTTP响应即可(例如Apache .htacccess“ AuthType Basic”模式)。

Vla*_*scu 5

我已经更新了Jonck van der Kogel的答案,使其在解析授权标头时更加严格,如果auth标头无效,则不会因难看的异常而失败,允许带有':'的密码,并可以与Play 2.6一起使用:

因此,BasicAuthAction类:

import java.io.UnsupportedEncodingException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import org.apache.commons.codec.binary.Base64;

import play.Logger;
import play.Logger.ALogger;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Http.Context;
import play.mvc.Result;

public class BasicAuthAction extends Action<Result> {
    private static ALogger log = Logger.of(BasicAuthAction.class);

    private static final String AUTHORIZATION = "Authorization";
    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
    private static final String REALM = "Basic realm=\"Realm\"";

    @Override
    public CompletionStage<Result> call(Context context) {
        String authHeader = context.request().getHeader(AUTHORIZATION);
        if (authHeader == null) {
            context.response().setHeader(WWW_AUTHENTICATE, REALM);
            return CompletableFuture.completedFuture(status(Http.Status.UNAUTHORIZED, "Needs authorization"));
        }

        String[] credentials;
        try {
            credentials = parseAuthHeader(authHeader);
        } catch (Exception e) {
            log.warn("Cannot parse basic auth info", e);
            return CompletableFuture.completedFuture(status(Http.Status.FORBIDDEN, "Invalid auth header"));
        }

        String username = credentials[0];
        String password = credentials[1];
        boolean loginCorrect = checkLogin(username, password);

        if (!loginCorrect) {
            log.warn("Incorrect basic auth login, username=" + username);
            return CompletableFuture.completedFuture(status(Http.Status.FORBIDDEN, "Forbidden"));
        } else {
            context.request().setUsername(username);
            log.info("Successful basic auth login, username=" + username);
            return delegate.call(context);
        }
    }

    private String[] parseAuthHeader(String authHeader) throws UnsupportedEncodingException {
        if (!authHeader.startsWith("Basic ")) {
            throw new IllegalArgumentException("Invalid Authorization header");
        }

        String[] credString;
        String auth = authHeader.substring(6);
        byte[] decodedAuth = new Base64().decode(auth);
        credString = new String(decodedAuth, "UTF-8").split(":", 2);
        if (credString.length != 2) {
            throw new IllegalArgumentException("Invalid Authorization header");
        }

        return credString;
    }

    private boolean checkLogin(String username, String password) {
        /// change this
        return username.equals("vlad");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在控制器类中:

@With(BasicAuthAction.class)
public Result authPage() {
    String username = request().username();
    return Result.ok("Successful login as user: " + username + "! Here's your data: ...");
}
Run Code Online (Sandbox Code Playgroud)