38.3. 自定义安全提供程序

我们能够通过Apusic应用服务器的安全框架来自定义自己的安全提供程序,下面以一个例子来描述如何在Apusic应用服务器上开发一个自定义的安全提供程序

38.3.1. 实体信息的存储与读取

这里讲述了如何开发一个有效的安全提供程序,这个例子描述的是通过配置文件存储用户和组的信息。用户的信息存储在user.conf文件中,组的信息存储在group.conf文件中。内容如下:

#在group.conf文件中定义的组信息如下:
group=administrator
group=manager
group=employee
在user.conf文件中定义的用户信息如下:
user=admin password=admin group=administrator
user=director password=director group=manager
user=operater password=operator group=employee

上面介绍了实体信息的存储,下面我们可以通过SimpleStore.java来完成对实体信息的读取操作

//SimpleStore.java
package com.apusic.demo.security.store;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.security.Principal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
public final class SimpleStore {
//从group.conf中读取的组信息
private static final Map<String, SimpleGroup> groups = new HashMap<String, SimpleGroup>();
//从user.conf中读取的用户信息
private static final Map<String, Principal> users = new HashMap<String, Principal>();
private static final SimpleStore store = new SimpleStore();
static {
try {
String groupEntry = null;
String groupName = null;
String userEntry = null;
String user = null;
String roles[] = null;
String password = null;
String elements[] = null;
SimpleGroup group = null;
SimplePrincipal principal = null;
//从group.conf中读取组信息
Iterator iterator = readEntry("group.conf");
while (iterator.hasNext()) {
groupEntry = (String) iterator.next();
if (groupEntry == null) {
continue;
}
elements = groupEntry.split("=");
if (elements.length == 2 && elements[0].equals("group")) {
groupName = elements[1];
groups.put(groupName, new SimpleGroup(groupName));
}
}
//从user.conf中读取用户信息,并设置用户所在的组
iterator = readEntry("user.conf");
while (iterator.hasNext()) {
userEntry = (String) iterator.next();
if (userEntry == null) {
continue;
}
elements = userEntry.split("\t");
if (elements.length == 3 && elements[0].startsWith("user=")
&& elements[1].startsWith("password=")
&& elements[2].startsWith("group=")) {
user = elements[0].substring(5);
password = elements[1].substring(9);
roles = elements[2].substring(6).split(",");
principal = new SimplePrincipal(user, password);
users.put(user, principal);
for (String role : roles) {
group = groups.get(role);
if (group != null) {
group.addMember(principal);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static SimpleStore getStore() {
return store;
}
public SimpleGroup getGroup(String group) {
return groups.get(group);
}
public Principal getUser(String user) {
return users.get(user);
}
private static Iterator readEntry(String file) throws IOException {
Vector vector = new Vector();
BufferedReader buffer = new BufferedReader(new FileReader(file));
String entry = null;
while (true) {
entry = buffer.readLine();
if (entry == null) {
break;
}
if (entry.trim().length() == 0 || entry.startsWith("#")) {
continue;
}
vector.add(entry);
}
vector.add(entry);
return vector.iterator();
}
}

38.3.2. 实现身份验证提供程序

为了实现自己的身份验证提供程序,我们需要实现com.apusic.security.realm.AuthenticationProvider接口,并实现下面的方法,示例如下:

 
//SimpleAuthentication实现
package com.apusic.demo.security.provider;
import java.security.Principal;
import com.apusic.demo.security.store.SimplePrincipal;
import com.apusic.demo.security.store.SimpleStore;
import com.apusic.security.Password;
import com.apusic.security.User;
import com.apusic.security.auth.login.PasswordCredential;
import com.apusic.security.config.RealmConfig;
import com.apusic.security.realm.AuthenticationProvider;
import com.apusic.security.realm.InitialException;
public class SimpleAuthentication implements AuthenticationProvider{
private SimpleStore store = SimpleStore.getStore();
//实现通过user.conf文件中查找是否存在对应的用户
public boolean authenticate(Object user, Object password) {
Principal principal = store.getUser((String) user);
if (principal == null) {
return false;
}
String pwd = new String(((PasswordCredential) password).getPassword());
if (principal instanceof SimplePrincipal) {
return ((SimplePrincipal)principal).getPassword().equals(pwd);
}
return false;
}
//用户的Provider可以不实现该接口,一般内部使用
public boolean authenticate(Object user, Object password, byte[] random) {
return false;
}
//资源的销毁
public void destroy() {
}
//实现通过user.conf文件中查找是否存在对应的用户
public Object findUser(String userId) {
User user = null;
Password password = null;
Principal principal = store.getUser(userId);
if (principal == null) {
return user;
}
if (principal instanceof SimplePrincipal) {
password = new Password(((SimplePrincipal)principal).getPassword());
user = new User(userId,password);
}
return user;
}
//用来完成一些初始化工作,如读取在security.xml文件中配置的参数...等信息
public void init(RealmConfig config) throws InitialException {
}
}

38.3.3. 实现授权提供程序

为了实现自己的授权验证提供程序,我们需要实现com.apusic.security.realm.AuthorizationProvider接口,并实现相关方法。示例如下:

//SimpleAuthorization实现
package com.apusic.demo.security.provider;
import java.security.acl.Group;
import com.apusic.demo.security.store.SimpleStore;
import com.apusic.security.config.RealmConfig;
import com.apusic.security.realm.AuthorizationProvider;
import com.apusic.security.realm.InitialException;
public class SimpleAuthorization implements AuthorizationProvider{
//资源的销毁
public void destroy() {
}
//实现通过group.conf文件中查找对应的组信息
public Group getGroup(String name) {
return SimpleStore.getStore().getGroup(name);
}
//用来完成一些初始化工作,如读取在security.xml文件中配置的参数...等信息
public void init(RealmConfig config) throws InitialException {
}
}
//SimpleGroup实现
package com.apusic.demo.security.store;
import java.security.Principal;
import java.security.acl.Group;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
public class SimpleGroup implements Group{
private List<Principal> members ;
private String name = null;
public SimpleGroup(String name) {
this.name = name;
members = new ArrayList<Principal>();
}
public boolean addMember(Principal user) {
return members.add(user);
}
public boolean isMember(Principal member) {
return members.contains(member);
}
public Enumeration<? extends Principal> members() {
return Collections.enumeration(members);
}
public boolean removeMember(Principal user) {
return members.remove(user);
}
public String getName() {
return this.name;
}
}

38.3.4. 配置映射

完成了上面的验证提供程序和授权提供程序后,我们需要在%DOMAIN_HOME%/config/security.xml文件中添加该安全提供程序,配置如下:

<realm>
<realm-name>SimpleRealm</realm-name>
<provider-type>Simple Provider</provider-type>
<authentication-provider>com.apusic.demo.security.SimpleAuthentication</authentication-provider>
<authorization-provider>com.apusic.demo.security.SimpleAuthorization</authorization-provider>
</realm>

到现在我们就可以在我们自己应用的apusic-application.xml文件中的指定下面的信息,通过SimpleRealm实现安全验证和授权。

 <realm-name>SimpleRealm</realm-name>