实现 UserAuthenticationSecurityCheck 类

improve this page | report issue

概述

此抽象类扩展 CredentialsValidationSecurityCheck,且基于其而构建以适合最常见的简单用户认证用例。除了验证凭证,它还创建了可从框架的各个部分访问的用户身份,从而使您能够标识当前用户。(可选)UserAuthenticationSecurityCheck 还提供记住我功能。

本教程使用的安全性检查示例会请求用户名和密码,并使用用户名来表示已认证的用户。

先决条件:确保阅读 CredentialsValidationSecurityCheck 教程。

跳转至:

创建安全性检查

创建 Java 适配器,并添加名为 UserLogin 且可扩展 UserAuthenticationSecurityCheck 的 Java 类。

public class UserLogin extends UserAuthenticationSecurityCheck {

    @Override
    protected AuthenticatedUser createUser() {
        return null;
    }

    @Override
    protected boolean validateCredentials(Map<String, Object> credentials) {
        return false;
    }

    @Override
    protected Map<String, Object> createChallenge() {
        return null;
    }
}

创建验证问题

验证问题与实现 CredentialsValidationSecurityCheck 中描述的内容完全相同。

@Override
protected Map<String, Object> createChallenge() {
    Map challenge = new HashMap();
    challenge.put("errorMsg",errorMsg);
    challenge.put("remainingAttempts",getRemainingAttempts());
    return challenge;
}

验证用户凭证

在客户机发送验证问题答案时,此答案会作为 Map 传递至 validateCredentials。使用此方法来实施您的逻辑。如果凭证是有效的,那么该方法将返回 true

在此示例中,在 usernamepassword 相同时,凭证被认为是“有效”的:

@Override
protected boolean validateCredentials(Map<String, Object> credentials) {
    if(credentials!=null && credentials.containsKey("username") && credentials.containsKey("password")){
        String username = credentials.get("username").toString();
        String password = credentials.get("password").toString();
        if(!username.isEmpty() && !password.isEmpty() && username.equals(password)) {
            return true;
        }
        else {
            errorMsg = "Wrong Credentials";
        }
    }
    else{
        errorMsg = "Credentials not set properly";
    }
    return false;
}

创建 AuthenticatedUser 对象

UserAuthenticationSecurityCheck 类在持久数据中存储当前客户机(用户、设备和应用程序)的表示,使您能够在代码的各个部分中检索当前用户,例如,验证问题处理程序或适配器。 通过类 AuthenticatedUser 的实例来表示用户。其构造方法采用 iddisplayNamesecurityCheckName 参数。

此示例针对 iddisplayName 参数使用 username

  1. 首先,修改 validateCredentials 方法以保存 username 自变量:

    private String userId, displayName;
    
    @Override
    protected boolean validateCredentials(Map<String, Object> credentials) {
         if(credentials!=null && credentials.containsKey("username") && credentials.containsKey("password")){
             String username = credentials.get("username").toString();
             String password = credentials.get("password").toString();
             if(!username.isEmpty() && !password.isEmpty() && username.equals(password)) {
                 userId = username;
                 displayName = username;
                 return true;
             }
             else {
                 errorMsg = "Wrong Credentials";
             }
         }
         else{
             errorMsg = "The credentials are not set properly.";
         }
         return false;
    }
    
  2. 然后,覆盖 createUser 方法以返回 AuthenticatedUser 的新实例:

    @Override
    protected AuthenticatedUser createUser() {
         return new AuthenticatedUser(userId, displayName, this.getName());
    }
    

您可以使用 this.getName() 来获取当前安全性检查名称。

在成功的 validateCredentials 之后,UserAuthenticationSecurityCheck 会调用 createUser() 实现。

在 AuthenticatedUser 中存储属性

AuthenticatedUser 具有一个替代构造方法:

AuthenticatedUser(String id, String displayName, String securityCheckName, Map<String, Object> attributes);

此构造方法添加要使用用户表示存储的定制属性的 Map。映射可用于存储其他信息,例如,个人档案图片、Web 站点等。此信息可供客户机端(验证问题处理程序)和资源(使用自省数据)访问。

注: 属性 Map 必须仅包含 Java 库中绑定的类型/类对象(例如,StringintMap 等),而不能包含定制类。

添加 RememberMe 功能

缺省情况下,UserAuthenticationSecurityCheck 使用 successStateExpirationSec 属性来确定成功状态的持续时间。此属性继承自 CredentialsValidationSecurityCheck

如果想要允许用户保持登录的时间超过 successStateExpirationSec 值,那么 UserAuthenticationSecurityCheck 可添加此功能。

UserAuthenticationSecurityCheck 会添加一个名为 rememberMeDurationSec 的属性,其缺省值为 0:缺省情况下,将记住用户 0 秒,这意味着缺省情况下禁用此功能。将该值更改为对您的应用程序有意义的数字(一天、一周、一个月……)。

您还可以通过覆盖 rememberCreatedUser() 方法来管理该功能,此方法缺省情况下返回 true,表示缺省情况下激活此功能(前提是更改了持续时间属性)。

在此示例中,客户通过发送 boolean 值作为所提交凭证的一部分来决定启用/禁用 RememberMe 功能。

  1. 首先,修改 validateCredentials 方法以保存 rememberMe 选择:

    private String userId, displayName;
    private boolean rememberMe = false;
    
    @Override
    protected boolean validateCredentials(Map<String, Object> credentials) {
         if(credentials!=null && credentials.containsKey("username") && credentials.containsKey("password")){
             String username = credentials.get("username").toString();
             String password = credentials.get("password").toString();
             if(!username.isEmpty() && !password.isEmpty() && username.equals(password)) {
                 userId = username;
                 displayName = username;
    
                 //Optional RememberMe
                 if(credentials.containsKey("rememberMe") ){
                     rememberMe = Boolean.valueOf(credentials.get("rememberMe").toString());
                 }
    
                 return true;
             }
             else {
                 errorMsg = "Wrong Credentials";
             }
         }
         else{
             errorMsg = "Credentials not set properly";
         }
         return false;
    }
    
  2. 然后,覆盖 rememberCreatedUser() 方法:

    @Override
    protected boolean rememberCreatedUser() {
         return rememberMe;
    }
    

配置安全性检查

adapter.xml 文件中,添加 <securityCheckDefinition> 元素:

<securityCheckDefinition name="UserLogin" class="com.sample.UserLogin">
  <property name="maxAttempts" defaultValue="3" description="How many attempts are allowed."/>
  <property name="blockedStateExpirationSec" defaultValue="10" description="How long before the client can try again (seconds)."/>
  <property name="successStateExpirationSec" defaultValue="60" description="How long is a successful state valid for (seconds)."/>
  <property name="rememberMeDurationSec" defaultValue="120" description="How long is the user remembered by the RememberMe feature (seconds)."/>
</securityCheckDefinition>

如前所述,UserAuthenticationSecurityCheck 继承所有 CredentialsValidationSecurityCheck 属性,例如,blockedStateExpirationSecsuccessStateExpirationSec 等。 此外,您还可以配置 rememberMeDurationSec 属性。

样本安全性检查

下载安全性检查 Maven 项目。

Maven 项目包含 UserAuthenticationSecurityCheck 的实现。

Last modified on February 23, 2017