Java 高级特性——安全,jaas登陆框架(二)
java 提供了 jaas 框架来对用户进行鉴权,本文主要从实战方面讲述如何使用 jaas 框架,最终完成登陆模块。
阅读本文的前置知识:Java 安全框架(策略文件的使用)
注:如果使用了 Java 模块,则需将登陆用到的自定义包导出
一、Jaas 框架介绍
注:LoginModule 和 CallbackHandler 可以不是一一对应的关系,LoginModule 可以对应多个 CallbackHandler
最简单的例子就是使用 jdk 提供的类来完成登陆请求,但是一般无法满足我们的需求。
要使用 jaas 框架首先我们需要打开安全管理器,然后调用相关的登陆代码来完成登陆,在这之前,先让我们来熟悉几个用到的类或接口。
1.LoginContext 类
LoginContext
公有方法代码如下:
public void login();
public void logout();
public Subject getSubject();
函数解释:
login()
:登陆logout()
:登出getSubject()
:获取当前登陆用户摘要信息
2.Principal类
Principal
接口,代码如下:
public interface Principal {
public boolean equals(Object another);
public String toString();
public int hashCode();
public String getName();
/*
* 蕴含关系,subject 是否蕴含当前的 Principal 主体
*/
public default boolean implies(Subject subject) {
if (subject == null)
return false;
return subject.getPrincipals().contains(this);
}
该接口表示了登陆主体,代表了登陆者的身份,通过 getName()
方法返回身份名。该接口在后续重点说明。
Principal
接口 jdk 提供了下面几种实现:
UserPrincipal
:使用用户名来表述当前登陆者的身份NtUserPrincipal
:也是使用用户名,不过用于 Windows 系统UnixPrincipal
:同上,不过用于 Unix 系统
可以通过在 policy 文件中配置 Principal
主体所拥有的权限,一个 Subject
可以有多个 Principal
。
LoginModule
的实现需要与 Principal
一一对应。
3.LoginModule 类
LoginModule
接口,代码如下:
public interface LoginModule {
void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String,?> sharedState,
Map<String,?> options);
boolean login() throws LoginException;
boolean commit() throws LoginException;
boolean abort() throws LoginException;
boolean logout() throws LoginException;
}
函数解释:
initialize()
:当新建一个LoginContext
时,Jaas会自动创建对应的LoginModule
并自动调用initialize()
,可以在此函数中进行初始化操作。login()
:当调用LoginContext.login()
时,jass自动调用该函数,完成登陆,如果该函数返回为true
并且没有异常抛出,则登陆成功。commit()
:登陆成功后,调用此函数。abort()
:如果LoginModule
整体验证失败,则调用该方法。logout()
:当调用LoginContext.logout()
时,自动调用该方法。
4.主要流程
Jaas 框架,主要的流程如下:
- 1.新建一个
LoginContext
,jaas通过传入的name
找到对应配置的用户名,然后利用配置信息找到对应的LoginModule
并实例化。 - 2.调用
LoginContext.login()
方法,jaas 会回调LoginModule.login()
方法进行登陆,如果该方法返回为true
并且没有抛出异常,则登陆成功。 - 3.如果用户登陆成功,jaas会回调
LoginModule.commit()
函数进行提交,可以在这里对用户进行授权。 - 4.如果在授权阶段发生异常,jaas会调用
LoginModule.abort()
函数。 - 5.调用
LoginContext.logout()
函数退出登陆。
5.相关的配置文件
jaas 有两个相关的配置文件,分别是 policy 文件和 config 文件。
policy 文件
- 命名:xxx.policy
- 使用方式:通过添加程序启动参数(前提,开启了securityManager),
java -Djava.security.policy==xxx.policy
policy 文件可以对代码和主体(Principal)进行授权配置,主要结构如下:
grant {
## 示例:permission xxx.Permission "name", "action";
permission javax.security.auth.AuthPermission "doAsPrivileged";
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.AuthPermission "createLoginContext";
permission java.util.PropertyPermission "os.name", "read";
permission javax.security.auth.AuthPermission "modifyPrincipals";
};
grant principal com.fy.login.internal.SimplePrincipal "user" {
permission java.util.PropertyPermission "user.*", "read";
};
有几个需要注意的点:
- 1.policy文件有严格的格式限制,每个授权块后面必须有分号,每行后面也必须有分号
- 2.如果没有 action,可省略 action 和 逗号,如果有,那么 name 后面必须加逗号。
- 3.授权主体(Principal)的配置如上所述,语法结构为
grant principal xxx.Principal "name"{ 权限列表 };
,这里的principal
表示当前授权对象是个Principal
类,xxx.Principal
表示自定义的Principal
实现类,"user"
表示当前授权主体的名称,该主体包含了一组权限。 - 4.关于
Principal
需要特别说明的是:我们最好实现它的equals()
和hashCode()
方法,并且在implies()
方法中利用这两个方法来判断该subject
是否蕴含该主体。
config 文件
- 命名:xxx.config
- 使用方式:通过添加程序启动参数(前提,开启了securityManager),
java -Djava.security.auth.login.config=xxx.config
config 文件主要功能是指定通过new LoginContext(name)
所对应name
要使用的LoginModule
类。例如,对ADMIN
用户,我们可以配置AdminLoginModule
类,进行更加严密的鉴权;而对USER
用户,使用相对简单的鉴权。
config 文件示例:
user
{
com.fy.login.internal.SimpleLoginModule required;
};
admin
{
com.fy.login.internal.SimpleLoginModule required;
};
注:该有的分号不能省略。
二、实现自定义登陆模块
- 通过 SPI 机制提供
IUserService
来实现密码获取和加载IValidateChain
来进行更严格的鉴权。 EventListeners
提供了静态的添加IEventListener
的方法来添加登陆登出监听。BaseMetadata
和NetMetadata
用来保存用户信息。- 通过
LoginManager.login(callback)
传入的CallbackHandler
来获取对应类型的Metadata
信息。
注:该框架仅是用来熟悉jaas的。
参考地址:https://gitee.com/zolmk/x-login
标签:jaas,Java,框架,LoginModule,登陆,login,public,Principal From: https://www.cnblogs.com/zolmk/p/16632340.html