理解Principal

Principal介绍

前面我们看quickstart项目源码时,用到了Subject,其实也用到了Credential,这也是我们需要理解的基础概念。

if (!currentUser.isAuthenticated()) {
    UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
    token.setRememberMe(true);
    try {
        currentUser.login(token);
    } catch (UnknownAccountException uae) {
        log.info("There is no user with username of " + token.getPrincipal());
    } catch (IncorrectCredentialsException ice) {
        log.info("Password for account " + token.getPrincipal() + " was incorrect!");
    } catch (LockedAccountException lae) {
        log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                "Please contact your administrator to unlock it.");
    }
    // ... catch more exceptions here (maybe custom ones specific to your application?
    catch (AuthenticationException ae) {
        //unexpected condition?  error?
    }
}

如果登录失败,那么我们会打印下token对象的Principal,如果修改代码在登录前后打印Subject和Token分别的Principal。

System.out.println("Subject principal: " + currentUser.getPrincipal());
System.out.println("Token principal " + token.getCredentials());

发现在调用login()函数前,Subject的Principal是null,而登录后Subject和Token的Principal都是lonestarr,也就是说在默认的Realm下Principal就是username字符串。

Principal源码

那么Principal究竟是什么呢,其实在Subject的源码中定义了Principal,就是用户的唯一标识,可以返回任意的Java对象,在前面的场景下返回的就是字符串类型的username。

/**
 * Returns this Subject's application-wide uniquely identifying principal, or {@code null} if this
 * Subject is anonymous because it doesn't yet have any associated account data (for example,
 * if they haven't logged in).
 * <p/>
 * The term <em>principal</em> is just a fancy security term for any identifying attribute(s) of an application
 * user, such as a username, or user id, or public key, or anything else you might use in your application to
 * identify a user.
 * <h4>Uniqueness</h4>
 * Although given names and family names (first/last) are technically considered principals as well,
 * Shiro expects the object returned from this method to be an identifying attribute unique across
 * your entire application.
 * <p/>
 * This implies that things like given names and family names are usually poor
 * candidates as return values since they are rarely guaranteed to be unique;  Things often used for this value:
 * <ul>
 * <li>A {@code long} RDBMS surrogate primary key</li>
 * <li>An application-unique username</li>
 * <li>A {@link java.util.UUID UUID}</li>
 * <li>An LDAP Unique ID</li>
 * </ul>
 * or any other similar suitable unique mechanism valuable to your application.
 * <p/>
 * Most implementations will simply return
 * <code>{@link #getPrincipals()}.{@link org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal() getPrimaryPrincipal()}</code>
 *
 * @return this Subject's application-specific unique identity.
 * @see org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
 */
Object getPrincipal();

而前面我们用的是UsernamePasswordToken,查看源码看到这个Token确实返回的是username字符串,然后login()时会回写到Subject对象中。

public Object getPrincipal() {
    return getUsername();
}

public String getUsername() {
    return username;
}

这里我们需要理解,Principal就是一个用户的标识,可以是username或者是自定义的User对象,Subject和Token都会包含这个信息,但不一定是同一个或者同种类型的对象。

results matching ""

    No results matching ""