iServer 提供了 Storage 接口来实现用户、角色、权限等安全信息的存储与管理。在实现自定义的存储方式时,需要实现Storage,形式如下:
public class JsonStorage implements Storage {
...
}
实现使用json文件来存储安全信息,本例将实现:
- 用户的存储:获取用户列表,以及添加、删除、修改用户
- 角色的存储:获取角色列表,以及添加、删除、修改角色
- 用户组的存储:获取用户组列表,以及添加、删除、修改用户组
- 用户、用户组、角色之间的关联信息
- 为角色授权
- 获取服务的授权信息
相应的方法包括:
| 功能类别 | 方法 | 描述 |
| 用户 | getUsers(int startIndex, int expectCount) getUser(String name) addUser(User toAdd) removeUsers(String[] names) alterUser(String name, User user) authenticate(String username, char[] password) | 获取、添加、删除、修改用户,以及将用户账户信息写入。 |
| 角色 | getRole(String name) getRoles(String username, Set<String> groups) getRoles(int startIndex, int expectCount) addRole(Role toAdd) removeRoles(String[] names) alterRole(String name, Role role) containOne(String[] roles, String theRole) insertRole(String roleName, String description) getRolePermissions(String[] names) setRolePermissions(String roleName, RolePermissions permission, ServiceBeanPermission[] permissions) | 获取、添加、删除、修改角色,在存储文件中插入角色信息,以及获取、设置角色授权。 |
| 用户组 | getGroups(int startIndex, int expectCount) getGroups(String username) addUserGroup(UserGroup toAdd) removeUserGroups(String[] names) alterUserGroup(String name, UserGroup userGroup) insertGroups(String GroupName, String description) | 获取、添加、删除、修改用户组,以及将用户组信息写入。 |
| 权限 | getPublicServiceNames() getPermission(String user, Collection<? extends String> groups, Collection<? extends String> roles, Set<String> resourceIds) getInstanceAuthorisations() updateInstanceAuthorisation(String name, AuthorizeSetting authorizeSetting) insert(ServiceBeanPermission[] permissions) | 获取服务列表,获取用户的授权信息,获取、更新服务实例的授权状态,以及将权限信息写入。 |
其他需要实现的方法有:
- resetStorageSetting() ,设置使用扩展的json存储方式
//设置使用扩展的json存储方式。
@Override
public void resetStorageSetting(SecurityInfoStorageSetting setting) {
if (!(setting instanceof JsonStorageSetting)) {
throw new IllegalArgumentException("only recieve JsonStorageSetting");
}
this.init((JsonStorageSetting) setting);
}
- init() ,读取配置的存储位置,并初始化一个json文件,用于存储安全信息
//读取配置的存储位置,并初始化一个json文件,用于存储安全信息。
private void init(JsonStorageSetting setting) {
String appFilePath = Tool.getApplicationPath(setting.outputDirectory);
this.storageFile = new File(appFilePath, SECURITY_FILE_NAME);
if (!this.storageFile.exists()) {
if (!this.storageFile.getParentFile().exists()) {
try {
FileUtils.forceMkdirParent(this.storageFile);
} catch (IOException e) {
throw new IllegalStateException("failed to make storage directory ");
}
}
try {
this.storageFile.createNewFile();
} catch (IOException e) {
throw new IllegalStateException("failed to make storage file ");
}
this.addPredefinedRoles();
this.addPredefinedGroups();
} else {
this.setMapContent();
}
}
@SuppressWarnings("unchecked")
private void setMapContent() {
try {
String json = FileUtils.readFileToString(this.storageFile, UTF_8);
Map<string, ?=""> statusMap = FastJSONUtils.parse(json, HashMap.class);
if (statusMap.containsKey(TAG_USERS)) {
this.users = (Map<string, user="">) statusMap.get(TAG_USERS);
}
if (statusMap.containsKey(TAG_ROLES)) {
this.roles = (Map<string, role="">) statusMap.get(TAG_ROLES);
}
if (statusMap.containsKey(TAG_USERGROUPS)) {
this.userGroups = (Map<string, usergroup="">) statusMap.get(TAG_USERGROUPS);
}
if (statusMap.containsKey(TAG_ROLEPERMISSIONS)) {
this.rolePermissions = (Map<string, rolepermissions="">) statusMap.get(TAG_ROLEPERMISSIONS);
}
if (statusMap.containsKey(TAG_AUTHORIZESETTING)) {
this.authorizeSetting = (Map<string, authorizesetting="">) statusMap.get(TAG_AUTHORIZESETTING);
}
if (statusMap.containsKey(TAG_SERVICEBEANPERMISSION)) {
this.serviceBeanPermission = (Map<string, servicebeanpermission="">) statusMap.get(TAG_SERVICEBEANPERMISSION);
}
} catch (IOException e) {
throw new IllegalStateException("JsonStorage init failed ");
}
}
- persistenceToFile(),把安全信息的当前状态,包括所有用户、角色、用户组以及权限的状态持久化到存储文件中
//把安全信息的当前状态,包括所有用户、角色、用户组以及权限的状态持久化到存储文件中。
private void persistenceToFile() {
Map<string, object=""> status = new HashMap<string, object="">();
status.put(TAG_USERS, users);
status.put(TAG_ROLES, roles);
status.put(TAG_USERGROUPS, userGroups);
status.put(TAG_ROLEPERMISSIONS, rolePermissions);
status.put(TAG_AUTHORIZESETTING, authorizeSetting);
status.put(TAG_SERVICEBEANPERMISSION, serviceBeanPermission);
String jsonStatus = FastJSONUtils.toFastJson(status);
jsonStatus = jsonFormat(jsonStatus);
try {
FileUtils.write(this.storageFile, jsonStatus, UTF_8);
} catch (IOException e) {
System.out.println("fail to persistence to " + this.storageFile.getAbsolutePath());
}
}
- batchGet() ,批量查询
//批量查询。
private QueryResult batchGet(int startIndex, int expectCount, List list) {
int actualCount = expectCount;
int size = list.size();
if (expectCount > size - startIndex || expectCount == 0) {
actualCount = size - startIndex;
}
List founds = new ArrayList ();
if (startIndex <= size)="" {="" int="" index="startIndex;" findcount="0;" while="" (findcount="" <="" actualcount)="" founds.add(list.get(index));="" index++;="" findcount++;="" }="" queryresult<t=""> queryResult = new QueryResult ();
queryResult.records = founds;
queryResult.totalCount = size;
return queryResult;
}
- ResolvingRolePermission() ,解析角色授权信息,使之转化为可存储的字符串。
//解析角色授权信息,使之转化为可存储的字符串。
private static class ResolvingRolePermission {
List<string> allowedCom = new LinkedList<string>();
List<string> deniedCom = new LinkedList<string>();
List<string> allowedService = new LinkedList<string>();
List<string> deniedService = new LinkedList<string>();
boolean isPublisher = false;
public RolePermissions toRolePermission() {
RolePermissions result = new RolePermissions();
result.publishEnabled = isPublisher;
result.componentManagerPermissions = new MixedPermissions();
result.componentManagerPermissions.denied = toArray(deniedCom);
result.componentManagerPermissions.permitted = toArray(allowedCom);
result.instanceAccessPermissions = new MixedPermissions();
result.instanceAccessPermissions.denied = toArray(deniedService);
result.instanceAccessPermissions.permitted = toArray(allowedService);
return result;
}
void add(int resourceType, String resourceName, int perm) {
List<string> list = null;
switch (resourceType) {
case RESOURCE_TYPE_PUBLISH: {
isPublisher = true;
break;
}
case RESOURCE_TYPE_COMPONENT: {
list = isAllowManageComponent(perm) ? allowedCom : deniedCom;
break;
}
case RESOURCE_TYPE_SERVICE: {
list = isAllowAccessService(perm) ? allowedService : deniedService;
break;
}
}
if (list != null) {
list.add(resourceName);
}
}
}
private static String[] toArray(List<string> list) {
return list.isEmpty() ? ArrayUtils.EMPTY_STRING_ARRAY : list.toArray(new String[list.size()]);
}
完整的扩展示例类如下:
NationalCacheStandardTileSourceInfo.java
package com.supermap.services.security.storages;
import static com.supermap.services.rest.resources.SecurityManageResource.ROLE_DESCRIPTION_ADMIN;
import static com.supermap.services.rest.resources.SecurityManageResource.ROLE_DESCRIPTION_PORTAL_USER;
import static com.supermap.services.rest.resources.SecurityManageResource.ROLE_DESCRIPTION_PUBLISHER;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.GROUP;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.RESOURCE_TYPE_COMPONENT;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.RESOURCE_TYPE_PUBLISH;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.RESOURCE_TYPE_SERVICE;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.ROLE;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.USER;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.isAllowAccessService;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.isAllowManageComponent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.credential.PasswordService;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.common.collect.Lists;
import com.supermap.server.config.JsonStorageSetting;
import com.supermap.server.config.SecurityInfoStorageSetting;
import com.supermap.services.components.commontypes.AuthorizeSetting;
import com.supermap.services.components.commontypes.AuthorizeType;
import com.supermap.services.rest.resources.SecurityManageResource;
import com.supermap.services.security.AuthenticateUsernamePasswordResult;
import com.supermap.services.security.AuthenticateUsernamePasswordResultType;
import com.supermap.services.security.MixedPermissions;
import com.supermap.services.security.QueryResult;
import com.supermap.services.security.Role;
import com.supermap.services.security.RolePermissions;
import com.supermap.services.security.SecurityConstants;
import com.supermap.services.security.ServiceBeanPermission;
import com.supermap.services.security.User;
import com.supermap.services.security.UserGroup;
import com.supermap.services.util.FastJSONUtils;
import com.supermap.services.util.IterableUtil;
import com.supermap.services.util.ProductTypeUtil;
import com.supermap.services.util.Tool;
import com.supermap.services.util.TypedResourceManager;
public class JsonStorage implements Storage {
private static final String SECURITY_FILE_NAME = "security.json";
private static final String UTF_8 = "utf-8";
private static final String TAG_USERS = "users";
private static final String TAG_ROLES = "roles";
private static final String TAG_USERGROUPS = "userGroups";
private static final String TAG_ROLEPERMISSIONS = "rolePermissions";
private static final String TAG_AUTHORIZESETTING = "authorizeSetting";
private static final String TAG_SERVICEBEANPERMISSION = "serviceBeanPermission";
private File storageFile;
private Map<String, Role> roles = new HashMap<String, Role>();
private Map<String, User> users = new HashMap<String, User>();
private Map<String, UserGroup> userGroups = new HashMap<String, UserGroup>();
private Map<String, RolePermissions> rolePermissions = new HashMap<String, RolePermissions>();
private Map<String, ServiceBeanPermission> serviceBeanPermission = new HashMap<String, ServiceBeanPermission>();
private Map<String, AuthorizeSetting> authorizeSetting = new HashMap<String, AuthorizeSetting>();
private Set<String> publicServiceNames = Collections.emptySet();
private PasswordService passwordService;
private static TypedResourceManager<SecurityManageResource> resource = new TypedResourceManager<SecurityManageResource>(SecurityManageResource.class);
private static final Collection<String> PUBLISHER_PERMISSIONS = Collections.unmodifiableList(Arrays.asList(StringUtils.split(
"interface:*,instance:*,component:*,componentset:*,provider:*,providerset:*,publish", ',')));
//设置使用扩展的json存储方式。
@Override
public void resetStorageSetting(SecurityInfoStorageSetting setting) {
if (!(setting instanceof JsonStorageSetting)) {
throw new IllegalArgumentException("only recieve JsonStorageSetting");
}
this.init((JsonStorageSetting) setting);
}
//读取配置的存储位置,并初始化一个json文件,用于存储安全信息。
private void init(JsonStorageSetting setting) {
String appFilePath = Tool.getApplicationPath(setting.outputDirectory);
this.storageFile = new File(appFilePath, SECURITY_FILE_NAME);
if (!this.storageFile.exists()) {
if (!this.storageFile.getParentFile().exists()) {
try {
FileUtils.forceMkdirParent(this.storageFile);
} catch (IOException e) {
throw new IllegalStateException("failed to make storage directory ");
}
}
try {
this.storageFile.createNewFile();
} catch (IOException e) {
throw new IllegalStateException("failed to make storage file ");
}
this.addPredefinedRoles();
this.addPredefinedGroups();
} else {
this.setMapContent();
}
}
@SuppressWarnings("unchecked")
private void setMapContent() {
try {
String json = FileUtils.readFileToString(this.storageFile, UTF_8);
Map<String, ?> statusMap = FastJSONUtils.parse(json, HashMap.class);
if (statusMap.containsKey(TAG_USERS)) {
this.users = (Map<String, User>) statusMap.get(TAG_USERS);
}
if (statusMap.containsKey(TAG_ROLES)) {
this.roles = (Map<String, Role>) statusMap.get(TAG_ROLES);
}
if (statusMap.containsKey(TAG_USERGROUPS)) {
this.userGroups = (Map<String, UserGroup>) statusMap.get(TAG_USERGROUPS);
}
if (statusMap.containsKey(TAG_ROLEPERMISSIONS)) {
this.rolePermissions = (Map<String, RolePermissions>) statusMap.get(TAG_ROLEPERMISSIONS);
}
if (statusMap.containsKey(TAG_AUTHORIZESETTING)) {
this.authorizeSetting = (Map<String, AuthorizeSetting>) statusMap.get(TAG_AUTHORIZESETTING);
}
if (statusMap.containsKey(TAG_SERVICEBEANPERMISSION)) {
this.serviceBeanPermission = (Map<String, ServiceBeanPermission>) statusMap.get(TAG_SERVICEBEANPERMISSION);
}
} catch (IOException e) {
throw new IllegalStateException("JsonStorage init failed ");
}
}
//添加系统预定义角色,包括"SYSTEM,ADMIN,PORTAL_USER,PUBLISHER"。
private void addPredefinedRoles() {
insertRole(SecurityConstants.ROLE_SYSTEM, StringUtils.EMPTY);
insertRole(SecurityConstants.ROLE_ADMIN, resource.message(ROLE_DESCRIPTION_ADMIN));
if (ProductTypeUtil.isPortal()) {
insertRole(SecurityConstants.ROLE_PORTAL_USER, resource.message(ROLE_DESCRIPTION_PORTAL_USER));
}
insertRole(SecurityConstants.ROLE_PUBLISHER, resource.message(ROLE_DESCRIPTION_PUBLISHER));
this.persistenceToFile();
}
//添加系统预定义的用户组。
private void addPredefinedGroups() {
insertGroups(SecurityConstants.GROUP_THIRD_PART_AUTHORIZED, StringUtils.EMPTY);
insertGroups(SecurityConstants.GROUP_LDAP_AUTHORIZED, StringUtils.EMPTY);
this.persistenceToFile();
}
//把安全信息的当前状态,包括所有用户、角色、用户组以及权限的状态持久化到存储文件中。
private void persistenceToFile() {
Map<String, Object> status = new HashMap<String, Object>();
status.put(TAG_USERS, users);
status.put(TAG_ROLES, roles);
status.put(TAG_USERGROUPS, userGroups);
status.put(TAG_ROLEPERMISSIONS, rolePermissions);
status.put(TAG_AUTHORIZESETTING, authorizeSetting);
status.put(TAG_SERVICEBEANPERMISSION, serviceBeanPermission);
String jsonStatus = FastJSONUtils.toFastJson(status);
jsonStatus = jsonFormat(jsonStatus);
try {
FileUtils.write(this.storageFile, jsonStatus, UTF_8);
} catch (IOException e) {
System.out.println("fail to persistence to " + this.storageFile.getAbsolutePath());
}
}
//格式化JSON。
private String jsonFormat(String jsonStatus) {
try {
JSONObject jsonObject = new JSONObject(jsonStatus);
return jsonObject.toString(4);
} catch (JSONException e1) {
// 永远走不到这里
return "";
}
}
//添加角色。
private void insertRole(String roleName, String description) {
Role role = new Role();
role.name = roleName;
role.description = description;
this.roles.put(roleName, role);
}
//添加用户组。
private void insertGroups(String GroupName, String description) {
UserGroup userGroup = new UserGroup();
userGroup.name = GroupName;
userGroup.description = description;
this.userGroups.put(GroupName, userGroup);
}
//根据角色获取用户列表。
@Override
public QueryResult<User> getUsers(int startIndex, int expectCount) {
ArrayList<User> userList = new ArrayList<User>();
List<String> ownRoles = new ArrayList<String>();
for (User user : this.users.values()) {
user.ownRoles = ownRoles.toArray(new String[ownRoles.size()]);
userList.add(user);
}
return batchGet(startIndex, expectCount, userList);
}
//根据用户名获取单个用户。
@Override
public User getUser(String name) {
return this.users.get(name);
}
//添加用户。
@Override
public void addUser(User toAdd) {
if (this.users.containsKey(toAdd.name)) {
throw new IllegalArgumentException("user " + toAdd.name + " exists yet");
}
this.users.put(toAdd.name, toAdd);
for (Role role : this.roles.values()) {
boolean containRoleInUser = containOne(toAdd.roles, role.name);
boolean containUserInRole = containOne(role.users, toAdd.name);
if (containRoleInUser && !containUserInRole) {
// 当前用户新增关联了一个角色。
role.users = ArrayUtils.add(role.users, toAdd.name);
}
}
for (UserGroup userGroup : this.userGroups.values()) {
String userGroupName = userGroup.name;
boolean containUserInUserGroup = containOne(userGroup.users, toAdd.name);
boolean containUserGroupInUser = containOne(toAdd.userGroups, userGroupName);
if (!containUserInUserGroup && containUserGroupInUser) {
// 当前用户新增关联了一个用户组。
userGroup.users = ArrayUtils.add(userGroup.users, toAdd.name);
}
}
this.persistenceToFile();
}
//批量删除用户。
@Override
public void removeUsers(String[] names) {
for (String name : names) {
User user = this.users.get(name);
this.users.remove(name);
for (Role role : this.roles.values()) {
boolean containUserInRole = containOne(role.users, user.name);
if (containUserInRole) {
// 当前用户解除关联了一个角色。
role.users = ArrayUtils.removeElement(role.users, user.name);
}
}
for (UserGroup userGroup : this.userGroups.values()) {
boolean containUserInGroup = containOne(userGroup.users, user.name);
if (containUserInGroup) {
// 当前用户解除关联了一个用户组。
userGroup.users = ArrayUtils.removeElement(userGroup.users, user.name);
}
}
}
this.persistenceToFile();
}
//修改用户信息,包括增加/减少关联的角色,增加/减少关联的用户组。
@Override
public void alterUser(String name, User user) {
this.users.put(name, user);
for (Role role : this.roles.values()) {
boolean containRoleInUser = containOne(user.roles, role.name);
boolean containUserInRole = containOne(role.users, user.name);
if (containRoleInUser && !containUserInRole) {
// 当前用户新增关联了一个角色。
role.users = ArrayUtils.add(role.users, user.name);
} else if (!containRoleInUser && containUserInRole) {
// 当前用户解除关联了一个角色。
role.users = ArrayUtils.removeElement(role.users, user.name);
}
}
for (UserGroup userGroup : this.userGroups.values()) {
String userGroupName = userGroup.name;
boolean containRoleInUser = containOne(userGroup.users, user.name);
boolean containUserInRole = containOne(user.userGroups, userGroupName);
if (containRoleInUser && !containUserInRole) {
// 当前用户解除关联了一个用户组。
userGroup.users = ArrayUtils.removeElement(userGroup.users, user.name);
} else if (!containRoleInUser && containUserInRole) {
// 当前用户新增关联了一个用户组。
userGroup.roles = ArrayUtils.add(userGroup.users, userGroupName);
}
}
this.persistenceToFile();
}
//添加用户组及关联的角色信息。
@Override
public void addUserGroup(UserGroup toAdd) {
if (this.userGroups.containsKey(toAdd.name)) {
throw new IllegalArgumentException("userGroups " + toAdd.name + " exists yet");
}
this.userGroups.put(toAdd.name, toAdd);
for (Role role : this.roles.values()) {
boolean containRoleInGroup = containOne(toAdd.roles, role.name);
boolean containGroupInRole = containOne(role.userGroups, toAdd.name);
if (containRoleInGroup && !containGroupInRole) {
// 当前用户组新增关联了一个角色。
role.userGroups = ArrayUtils.add(role.userGroups, toAdd.name);
}
}
for (User user : this.users.values()) {
boolean containUserInGroup = containOne(toAdd.users, user.name);
boolean containGroupInUser = containOne(user.userGroups, toAdd.name);
if (containUserInGroup && !containGroupInUser) {
// 当前用户组新增关联了一个用户。
user.userGroups = ArrayUtils.add(user.userGroups, toAdd.name);
}
}
this.persistenceToFile();
}
//修改用户组信息,包括增加/减少关联的角色,增加/减少关联的用户组。
@Override
public void alterUserGroup(String name, UserGroup userGroup) {
this.userGroups.put(name, userGroup);
for (User user : this.users.values()) {
String userName = user.name;
boolean containGroupInUser = containOne(user.userGroups, userGroup.name);
boolean containUserInGroup = containOne(userGroup.users, userName);
if (containGroupInUser && !containUserInGroup) {
// 当前用户组解除关联了一个用户。
user.userGroups = ArrayUtils.removeElement(user.userGroups, userGroup.name);
} else if (!containGroupInUser && containUserInGroup) {
// 当前用户新增关联了一个用户。
user.userGroups = ArrayUtils.add(user.userGroups, userGroup.name);
}
}
for (Role role : this.roles.values()) {
String roleName = role.name;
boolean containGroupInRole = containOne(role.userGroups, userGroup.name);
boolean containRoleInGroup = containOne(userGroup.roles, roleName);
if (containGroupInRole && !containRoleInGroup) {
// 当前用户组新增关联了一个角色。
role.userGroups = ArrayUtils.removeElement(role.userGroups, userGroup.name);
} else if (!containGroupInRole && containRoleInGroup) {
// 当前用户组解除关联了一个角色。
role.userGroups = ArrayUtils.add(role.userGroups, userGroup.name);
}
}
this.persistenceToFile();
}
//删除用户组。
@Override
public void removeUserGroups(String[] names) {
for (String name : names) {
UserGroup userGroup = this.userGroups.get(name);
this.userGroups.remove(name);
for (Role role : this.roles.values()) {
boolean containRoleInGroup = containOne(role.userGroups, userGroup.name);
if (containRoleInGroup) {
// 当前用户组解除关联了一个角色。
role.userGroups = ArrayUtils.removeElement(role.userGroups, userGroup.name);
}
}
for (User user : this.users.values()) {
boolean containUserInGroup = containOne(user.userGroups, userGroup.name);
if (containUserInGroup) {
// 当前用户组解除关联了一个用户。
user.userGroups = ArrayUtils.removeElement(user.userGroups, userGroup.name);
}
}
}
this.persistenceToFile();
}
//获取用户组。
@Override
public QueryResult<UserGroup> getGroups(int startIndex, int expectCount) {
ArrayList<UserGroup> userGroupList = new ArrayList<UserGroup>();
for (UserGroup userGroup : this.userGroups.values()) {
userGroupList.add(userGroup);
}
return this.batchGet(startIndex, expectCount, userGroupList);
}
//添加角色。
@Override
public void addRole(Role toAdd) {
if (this.roles.containsKey(toAdd.name)) {
throw new IllegalArgumentException("roles" + toAdd.name + " exists yet");
}
this.roles.put(toAdd.name, toAdd);
for (User user : this.users.values()) {
boolean containUserInRole = containOne(toAdd.users, user.name);
boolean containRoleInUser = containOne(user.roles, toAdd.name);
if (containUserInRole && !containRoleInUser) {
// 当前角色新增关联了一个用户。
user.roles = ArrayUtils.add(user.roles, toAdd.name);
}
}
for (UserGroup userGroup : this.userGroups.values()) {
String userGroupName = userGroup.name;
boolean containGroupInRole = containOne(toAdd.userGroups, userGroupName);
boolean containRoleInGroup = containOne(userGroup.roles, toAdd.name);
if (containGroupInRole && !containRoleInGroup) {
// 当前角色关联了一个用户组。
userGroup.roles = ArrayUtils.add(userGroup.roles, toAdd.name);
}
}
this.persistenceToFile();
}
//修改角色。
@Override
public void alterRole(String name, Role role) {
this.roles.put(name, role);
String roleName = role.name;
// 修改关联的用户信息
for (User user : this.users.values()) {
String userName = user.name;
boolean containRoleInUser = containOne(user.roles, roleName);
boolean containUserInRole = containOne(role.users, userName);
if (containRoleInUser && !containUserInRole) {
// 当前角色解除关联了一个用户。
user.roles = ArrayUtils.removeElement(user.roles, roleName);
} else if (!containRoleInUser && containUserInRole) {
// 当前角色新增关联了一个用户。
user.roles = ArrayUtils.add(user.roles, roleName);
}
}
for (UserGroup userGroup : this.userGroups.values()) {
String userGroupName = userGroup.name;
boolean containRoleInUser = containOne(userGroup.roles, roleName);
boolean containUserInRole = containOne(role.userGroups, userGroupName);
if (containRoleInUser && !containUserInRole) {
// 当前角色解除关联了一个用户组。
userGroup.roles = ArrayUtils.removeElement(userGroup.roles, roleName);
} else if (!containRoleInUser && containUserInRole) {
// 当前角色新增关联了一个用户组。
userGroup.roles = ArrayUtils.add(userGroup.roles, roleName);
}
}
this.persistenceToFile();
}
//批量删除角色。
@Override
public void removeRoles(String[] names) {
for (String name : names) {
Role role = this.roles.get(name);
this.roles.remove(name);
for (User user : this.users.values()) {
boolean containRoleInUser = containOne(user.roles, role.name);
if (containRoleInUser) {
// 当前角色解除关联了一个用户。
user.roles = ArrayUtils.removeElement(user.roles, role.name);
}
}
for (UserGroup userGroup : this.userGroups.values()) {
boolean containRoleInGroup= containOne(userGroup.roles, role.name);
if (containRoleInGroup) {
// 当前角色解除关联了一个用户组。
userGroup.roles = ArrayUtils.removeElement(userGroup.roles, role.name);
}
}
}
this.persistenceToFile();
}
//根据角色名获取一个角色。
@Override
public Role getRole(String name) {
return this.roles.get(name);
}
//获取用户组列表。
@Override
public Set<String> getGroups(String username) {
Set<String> result = new LinkedHashSet<String>();
if (!StringUtils.isEmpty(username)) {
User user = this.users.get(username);
if (user != null && !ArrayUtils.isEmpty(user.userGroups)) {
result.addAll(Lists.asList(null, user.userGroups));
}
}
return result;
}
//获取一个户名所关联的角色列表。
@Override
public Set<String> getRoles(String username, Set<String> groups) {
Set<String> result = new LinkedHashSet<String>();
if (!StringUtils.isEmpty(username)) {
User user = this.users.get(username);
if (user != null && !ArrayUtils.isEmpty(user.roles)) {
result.addAll(Lists.asList(null, user.roles));
}
}
if (groups != null && !groups.isEmpty()) {
for (String groupName : groups) {
if (StringUtils.isEmpty(groupName)) {
continue;
}
UserGroup ug = this.userGroups.get(groupName);
if (ug != null && !ArrayUtils.isEmpty(ug.roles)) {
result.addAll(Lists.asList(null, ug.roles));
}
}
}
return result;
}
//根据索引和数量获取角色列表。
@Override
public QueryResult<Role> getRoles(int startIndex, int expectCount) {
ArrayList<Role> roleList = new ArrayList<Role>();
for (Role role : this.roles.values()) {
roleList.add(role);
}
return this.batchGet(startIndex, expectCount, roleList);
}
//获取发布的所有服务列表。
@Override
public Set<String> getPublicServiceNames() {
return publicServiceNames;
}
//为角色设置权限。
@Override
public void setRolePermissions(String roleName, RolePermissions permission, ServiceBeanPermission[] permissions) {
if (permission == null) {
return;
}
final Set<ServiceBeanPermission> records = new LinkedHashSet<ServiceBeanPermission>();
if (permission.publishEnabled) {
records.add(new ServiceBeanPermission().publish().role(roleName));
records.add(new ServiceBeanPermission().allowViewAllInterface().role(roleName));
}
MixedPermissions mngPermission = permission.componentManagerPermissions;
if (mngPermission != null) {
if (mngPermission.permitted != null) {
for (String com : mngPermission.permitted) {
records.add(new ServiceBeanPermission().allowComponent(com).role(roleName));
}
}
if (mngPermission.denied != null) {
for (String com : mngPermission.denied) {
records.add(new ServiceBeanPermission().denyComponent(com).role(roleName));
}
}
}
final List<String> deniedServices = new ArrayList<String>();
MixedPermissions accessPermission = permission.instanceAccessPermissions;
if (accessPermission != null) {
if (accessPermission.permitted != null) {
for (String service : accessPermission.permitted) {
records.add(new ServiceBeanPermission().allowAccessService(service).role(roleName));
}
}
if (accessPermission.denied != null) {
for (String service : accessPermission.denied) {
records.add(new ServiceBeanPermission().denyAccessService(service).role(roleName));
deniedServices.add(service);
}
}
}
if (!ArrayUtils.isEmpty(permissions)) {
records.addAll(Arrays.asList(permissions));
}
for (ServiceBeanPermission serbeanPermission : records) {
this.serviceBeanPermission.put(serbeanPermission.principal, serbeanPermission);
}
this.persistenceToFile();
}
//获取一个用户的权限。
@Override
public Set<String> getPermission(String user, Collection<? extends String> groups, Collection<? extends String> roles, Set<String> resourceIds) {
Set<String> result = new LinkedHashSet<String>();
int initialCapacity = 1;
initialCapacity += groups == null ? 0 : groups.size();
initialCapacity += roles == null ? 0 : roles.size();
final Set<String> principals = new LinkedHashSet<String>(initialCapacity);
if (StringUtils.isNotEmpty(user)) {
principals.add(USER + user);
}
add(principals, groups, GROUP);
add(principals, roles, ROLE);
if (principals.isEmpty()) {
return Collections.emptySet();
}
final boolean isPublisher = principals.remove("ROLE^PUBLISHER");
if (isPublisher) {
result.addAll(PUBLISHER_PERMISSIONS);
} else {
for (String principal : principals) {
ServiceBeanPermission sp = this.serviceBeanPermission.get(principal);
if (sp == null) {
continue;
}
result.add(sp.shiroPermission);
}
}
return result;
}
//获取一个角色的权限。
@Override
public Map<String, RolePermissions> getRolePermissions(String[] names) {
if (ArrayUtils.isEmpty(names)) {
return Collections.emptyMap();
}
String[] roles = new String[names.length];
for (int i = 0; i < roles.length; i++) {
roles[i] = ROLE + names[i];
}
List<ServiceBeanPermission> sqlResult = new ArrayList<ServiceBeanPermission>();
for (ServiceBeanPermission serviceBeanPer : this.serviceBeanPermission.values()) {
int[] a = new int[] { RESOURCE_TYPE_COMPONENT, RESOURCE_TYPE_SERVICE, RESOURCE_TYPE_PUBLISH };
if (ArrayUtils.contains(roles, serviceBeanPer) && serviceBeanPer.principaltype == 2 && ArrayUtils.contains(a, serviceBeanPer.resourcetype)) {
sqlResult.add(serviceBeanPer);
}
}
Map<String, ResolvingRolePermission> resolvingResult = new HashMap<String, ResolvingRolePermission>();
for (ServiceBeanPermission serviceBean : sqlResult) {
if (!StringUtils.startsWith(serviceBean.principal, ROLE)) {
continue;
}
String roleName = serviceBean.principal.substring(ROLE.length());
ResolvingRolePermission rolePermission = resolvingResult.get(roleName);
if (rolePermission == null) {
rolePermission = new ResolvingRolePermission();
resolvingResult.put(roleName, rolePermission);
}
rolePermission.add(serviceBean.resourcetype, serviceBean.resource, serviceBean.permission);
}
final Map<String, RolePermissions> result = new HashMap<String, RolePermissions>();
IterableUtil.iterate(resolvingResult.entrySet(), new IterableUtil.Visitor<Entry<String, ResolvingRolePermission>>() {
@Override
public boolean visit(Entry<String, ResolvingRolePermission> element) {
result.put(element.getKey(), element.getValue().toRolePermission());
return false;
}
});
return result;
}
//更新一个服务实例的授权信息。
@Override
public void updateInstanceAuthorisation(String name, AuthorizeSetting authorizeSetting) {
final Set<ServiceBeanPermission> records = new LinkedHashSet<ServiceBeanPermission>();
if (AuthorizeType.PUBLIC.equals(authorizeSetting.type)) {
records.add(new ServiceBeanPermission().role(SecurityConstants.ROLE_EVERYONE).allowAccessService(name));
} else if (AuthorizeType.AUTHENTICATED.equals(authorizeSetting.type)) {
records.add(new ServiceBeanPermission().role(SecurityConstants.ROLE_USER).allowAccessService(name));
}
if (!ArrayUtils.isEmpty(authorizeSetting.deniedRoles)) {
for (String role : authorizeSetting.deniedRoles) {
if (StringUtils.isEmpty(role)) {
continue;
}
records.add(new ServiceBeanPermission().role(role).denyAccessService(name));
}
}
if (!ArrayUtils.isEmpty(authorizeSetting.permittedRoles)) {
for (String role : authorizeSetting.permittedRoles) {
if (StringUtils.isEmpty(role)) {
continue;
}
records.add(new ServiceBeanPermission().role(role).allowAccessService(name));
}
}
int[] a = new int[] {RESOURCE_TYPE_SERVICE};
for (ServiceBeanPermission serviceBeanPer : this.serviceBeanPermission.values()) {
if (ArrayUtils.contains(a, serviceBeanPer.resourcetype)&&serviceBeanPer.resource.equals(name)) {
this.serviceBeanPermission.remove(serviceBeanPer.principal);
}
}
for (ServiceBeanPermission record : records) {
this.serviceBeanPermission.put(record.principal, record);
}
this.persistenceToFile();
}
//获取服务实例的授权信息。
@Override
public Map<String, AuthorizeSetting> getInstanceAuthorisations() {
int[] a = new int[] {RESOURCE_TYPE_SERVICE};
List<ServiceBeanPermission> serviceBeanResults = new ArrayList<ServiceBeanPermission>();
for (ServiceBeanPermission serviceBeanPer : this.serviceBeanPermission.values()) {
if (ArrayUtils.contains(a, serviceBeanPer.resourcetype)) {
serviceBeanResults.add(serviceBeanPer);
}
}
Map<String, QueryingAuthorizeSetting> querying = new HashMap<String, QueryingAuthorizeSetting>();
for (ServiceBeanPermission serviceBean : serviceBeanResults) {
String instanceName = serviceBean.resource;
QueryingAuthorizeSetting setting = querying.get(instanceName);
if (setting == null) {
setting = new QueryingAuthorizeSetting();
querying.put(instanceName, setting);
}
int permission = serviceBean.permission;
String role = serviceBean.principal;
if (isAllowAccessService(permission)) {
setting.allowedRole(role);
} else {
setting.deniedRole(role);
}
}
if (querying.isEmpty()) {
return Collections.emptyMap();
}
Map<String, AuthorizeSetting> result = new HashMap<String, AuthorizeSetting>(querying.size());
Iterator<Entry<String, QueryingAuthorizeSetting>> it = querying.entrySet().iterator();
while (it.hasNext()) {
Entry<String, QueryingAuthorizeSetting> entry = it.next();
result.put(entry.getKey(), entry.getValue().toAuthorizeSetting());
}
return result;
}
@Override
public void grantUser(String username, RolePermissions permission) {
}
//增加一条权限信息。
@Override
public void insert(ServiceBeanPermission[] permissions) {
if (ArrayUtils.isEmpty(permissions)) {
return;
}
for (ServiceBeanPermission permission : permissions) {
this.serviceBeanPermission.put(permission.principal, permission);
}
this.persistenceToFile();
}
@Override
public void setPasswordService(PasswordService value) {
this.passwordService = value;
}
//存储用户的账户信息。
@Override
public AuthenticateUsernamePasswordResult authenticate(String username, char[] password) {
User user = this.getUser(username);
AuthenticateUsernamePasswordResult result = new AuthenticateUsernamePasswordResult();
if (user != null) {
result.type = this.passwordService.passwordsMatch(password, user.password) ? AuthenticateUsernamePasswordResultType.VALIED
: AuthenticateUsernamePasswordResultType.INVALID;
}
return result;
}
private void add(Set<String> toAddIn, Collection<? extends String> toAdd, String prefix) {
if (toAdd == null || toAdd.isEmpty()) {
return;
}
for (String str : toAdd) {
toAddIn.add(prefix + str);
}
}
//查询是否存在某个角色。
private boolean containOne(String[] roles, String theRole) {
if (ArrayUtils.isEmpty(roles)) {
return false;
}
return ArrayUtils.contains(roles, theRole);
}
//批量查询。
private <T> QueryResult<T> batchGet(int startIndex, int expectCount, List<T> list) {
int actualCount = expectCount;
int size = list.size();
if (expectCount > size - startIndex || expectCount == 0) {
actualCount = size - startIndex;
}
List<T> founds = new ArrayList<T>();
if (startIndex <= size) {
int index = startIndex;
int findCount = 0;
while (findCount < actualCount) {
founds.add(list.get(index));
index++;
findCount++;
}
}
QueryResult<T> queryResult = new QueryResult<T>();
queryResult.records = founds;
queryResult.totalCount = size;
return queryResult;
}
//解析角色授权信息,使之转化为可存储的字符串。
private static class ResolvingRolePermission {
List<String> allowedCom = new LinkedList<String>();
List<String> deniedCom = new LinkedList<String>();
List<String> allowedService = new LinkedList<String>();
List<String> deniedService = new LinkedList<String>();
boolean isPublisher = false;
public RolePermissions toRolePermission() {
RolePermissions result = new RolePermissions();
result.publishEnabled = isPublisher;
result.componentManagerPermissions = new MixedPermissions();
result.componentManagerPermissions.denied = toArray(deniedCom);
result.componentManagerPermissions.permitted = toArray(allowedCom);
result.instanceAccessPermissions = new MixedPermissions();
result.instanceAccessPermissions.denied = toArray(deniedService);
result.instanceAccessPermissions.permitted = toArray(allowedService);
return result;
}
void add(int resourceType, String resourceName, int perm) {
List<String> list = null;
switch (resourceType) {
case RESOURCE_TYPE_PUBLISH: {
isPublisher = true;
break;
}
case RESOURCE_TYPE_COMPONENT: {
list = isAllowManageComponent(perm) ? allowedCom : deniedCom;
break;
}
case RESOURCE_TYPE_SERVICE: {
list = isAllowAccessService(perm) ? allowedService : deniedService;
break;
}
}
if (list != null) {
list.add(resourceName);
}
}
}
private static String[] toArray(List<String> list) {
return list.isEmpty() ? ArrayUtils.EMPTY_STRING_ARRAY : list.toArray(new String[list.size()]);
}
static class QueryingAuthorizeSetting {
AuthorizeType type;
Set<String> deniedRoles = new LinkedHashSet<String>();
Set<String> allowedRoles = new LinkedHashSet<String>();
QueryingAuthorizeSetting allowedRole(String value) {
String role = value.substring(ROLE.length());
if (type == null && SecurityConstants.ROLE_USER.equals(role)) {
type = AuthorizeType.AUTHENTICATED;
} else if (SecurityConstants.ROLE_EVERYONE.equals(role)) {
type = AuthorizeType.PUBLIC;
} else {
allowedRoles.add(role);
}
return this;
}
QueryingAuthorizeSetting deniedRole(String value) {
deniedRoles.add(value.substring(ROLE.length()));
return this;
}
AuthorizeSetting toAuthorizeSetting() {
AuthorizeSetting result = new AuthorizeSetting();
result.type = type == null ? AuthorizeType.PRIVATE : type;
result.deniedRoles = deniedRoles.toArray(new String[deniedRoles.size()]);
result.permittedRoles = allowedRoles.toArray(new String[allowedRoles.size()]);
return result;
}
}
@Override
public void removeInstances(String[] names) {
}
@Override
public void renameInstance(String oldName, String newName) {
}
@Override
public void setFormPasswordSavedCount(int passwordDiffCount) {
}
@Override
public void dispose() {
}
}