13.2 用户认证
用户认证是用户向系统表明身份并由系统进行验证的过程。系统中的某些功能是认证用户才可以使用的。为了使用这些功能,用户需要先向系统表明身份,然后系统进行必要的身份认证。验证成功之后,当前用户变为认证用户,具备对应的基本权限。
13.2.1 主体、身份标识与凭证
在Java安全中用术语“主体(subject)”来表示访问请求的来源。主体是一个抽象的概念,可以表示任何实体。主体的具体含义由系统本身来确定,通常的理解是把主体看成系统的用户。这些用户可以是具体的人,也可以是其他程序。比如,对一个电子商务网站来说,用户可能是购买商品的消费者,也可能是合作商家,还可能是搜索引擎的抓取爬虫程序。
一个主体可以有多个不同的身份标识(principal)。身份标识是主体的具体表示。最常见的身份标识是系统分配或用户自己注册的用户名。在有的系统中,一个用户可以有多个身份标识。比如,用户注册的用户名和手机号码等都可以作为用户认证时的身份标识。
除了身份标识之外,一个主体还可以有公开或私有的安全相关的凭证(credential),包括密码和密钥等。最典型的凭证是用户注册时设置的密码。凭证是用户拥有一个身份标识的依据。
Java API中表示主体的是javax.security.auth.Subject类,表示用户身份标识的是java.security.Principal接口。一个主体可以与多个身份标识关联。通过Subject类的getPrincipals方法可以得到包含当前主体关联的所有Principal接口的实现对象的集合。主体所关联的凭证信息分成公开和私有两类。公开凭证包括公钥等,通过Subject类的getPublicCredentials方法获取所包含的公开凭证对象的集合;私有凭证包括密码和私钥等,通过Subject类的对应方法getPrivateCredentials来获取。对于身份标识和凭证,Subject类都是使用java.util.Set接口来管理,通过使用返回的Set接口的实现对象中的方法来完成对身份标识及凭证的添加和删除等操作。Principal接口中的重要方法是getName,用来返回String类型的身份标识的名称。Principal接口的具体实现类可以为该身份标识设置不同的含义,比如代码清单13-1中的UserPrincipal类中使用的身份标识是用户名。Subject类对于凭证的具体表示方式并没有做出限制,任何对象都可以作为凭证。
代码清单13-1 Principal接口实现类的示例
public class UserPrincipal implements Principal{
private final String username;
public UserPrincipal(String username){
this.username=username;
}
public String getName(){
return username;
}
}
为了防止程序中的其他代码对Subject类的对象进行错误的修改,可以在添加必要的身份标识和凭证信息之后,调用setReadOnly方法把Subject类的对象设为只读状态。一旦被设为只读状态,该Subject类的对象无法被重新设置为可修改状态。