package com.taobao.easyweb.security; import groovy.lang.Script; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.taobao.easyweb.core.PaginationResult; import com.taobao.easyweb.core.Result; import com.taobao.easyweb.core.context.ThreadContext; import com.taobao.easyweb.security.annotation.OnPerm; import com.taobao.easyweb.security.dao.PermissionDAO; import com.taobao.easyweb.security.dao.RoleDAO; import com.taobao.easyweb.security.dao.UserDAO; import com.taobao.easyweb.security.domain.Permission; import com.taobao.easyweb.security.domain.Role; import com.taobao.easyweb.security.domain.User; @Component("ewSecurityManager") public class SecurityManager { @Resource(name = "ewUserDAO") private UserDAO userDAO; @Resource(name = "ewRoleDAO") private RoleDAO roleDAO; @Resource(name = "ewPermissionDAO") private PermissionDAO permissionDAO; // private Logger logger = LoggerUtil.getLogger(); public static Map<String, List<MethodSecurity>> securities = new ConcurrentHashMap<String, List<MethodSecurity>>(); public static Map<String, OnPerm> methodOnPerms = new ConcurrentHashMap<String, OnPerm>(); public static void add(Script script, String method, List<String> keys) { modified = true; for (String key : keys) { MethodSecurity methodSecurity = new MethodSecurity(); methodSecurity.setKey(key); methodSecurity.setClassName(script.getClass().getSimpleName()); methodSecurity.setPackageName(script.getClass().getPackage().getName()); methodSecurity.setMessages(keys.toString()); methodSecurity.setMethod(method); add(key, methodSecurity); } } public static void remove(Script script, String method, List<String> keys) { for (String key : keys) { MethodSecurity methodSecurity = new MethodSecurity(); methodSecurity.setKey(key); methodSecurity.setClassName(script.getClass().getSimpleName()); methodSecurity.setPackageName(script.getClass().getPackage().getName()); methodSecurity.setMessages(keys.toString()); methodSecurity.setMethod(method); if (securities.containsKey(key)) { securities.get(key).remove(methodSecurity); } } } private static void add(String key, MethodSecurity methodSecurity) { if (!securities.containsKey(key)) { securities.put(key, new ArrayList<MethodSecurity>()); } securities.get(key).add(methodSecurity); } /** * ע��Ȩ�޶����ڴ��������ʱ����� * * @param key * @param description * @return */ public Permission regist(String key, String description) { Permission permission = permissionDAO.queryByKey(key); if (permission != null) { return permission; } permission = new Permission(); permission.setKey(key); permission.setDescription(description); permissionDAO.save(permission); return permission; } /** * ��ʱֻɾ��Ȩ�޶��󣬲�ɾ������Ȩ�� * * @param permissionId * @return */ public boolean deletePermission(Integer permissionId) { int size = permissionDAO.delete(permissionId); return size > 0; } public Result<String> addUserPermission(Integer userId, Integer permissionId) { Result<String> result = new Result<String>(false); Permission permission = permissionDAO.queryById(permissionId); if (permission == null) { result.addErrorMessage("Ȩ�޲����� id=" + permissionId); return result; } User user = userDAO.queryById(userId); if (user == null) { result.addErrorMessage("�û������� id=" + userId); return result; } result.setSuccess(true); userDAO.applyPermission(userId, permissionId); userPermissions.refresh(userId); return result; } public void addUserRole(Integer userId, Integer roleId) { userDAO.addRole(userId, roleId); userPermissions.refresh(userId); } public void deleteUserRole(Integer userId, Integer roleId) { userDAO.deleteRole(userId, roleId); userPermissions.refresh(userId); } public boolean removeUserPermission(Integer userId, Integer permissionId) { userDAO.removePermission(userId, permissionId); userPermissions.refresh(userId); return true; } public boolean addRolePermission(Integer roleId, Integer permissionId) { Permission permission = permissionDAO.queryById(permissionId); if (permission == null) { return false; } Role role = roleDAO.queryById(roleId); if (role == null) { return false; } roleDAO.applyPermission(roleId, permissionId); refreshRole(roleId); return true; } public boolean removeRolePermission(Integer roleId, Integer permissionId) { roleDAO.removePermission(roleId, permissionId); refreshRole(roleId); return true; } private void refreshRole(Integer roleId) { List<Integer> users = queryRoleUserIds(roleId); for (Integer user : users) { userPermissions.refresh(user); } } public List<Permission> queryRolePermissions(Integer roleId) { List<Integer> ids = roleDAO.queryRolePermissions(roleId); return permissionDAO.queryByIds(ids); } public List<Integer> queryRolePermissionIds(Integer roleId) { return roleDAO.queryRolePermissions(roleId); } public Role queryRoleInfo(Integer roleId) { return roleDAO.queryById(roleId); } public Result<String> addOrUpdateRole(Role role) { Result<String> result = new Result<String>(false); if (StringUtils.isBlank(role.getName())) { result.addErrorMessage("��ɫ���Ʋ���Ϊ��"); return result; } Role tmp = roleDAO.queryByName(role.getName()); if (tmp == null && role.getId() == null) { roleDAO.save(role); result.setSuccess(true); return result; } if (role.getId() != null && tmp == null) { tmp = new Role(); tmp.setId(role.getId()); tmp.setName(role.getName()); tmp.setDescription(role.getDescription()); roleDAO.update(tmp); } result.setSuccess(true); return result; } public List<User> queryRoleUsers(Integer roleId) { List<Integer> ids = roleDAO.queryRoleUsers(roleId); return userDAO.queryByIds(ids); } public List<Integer> queryRoleUserIds(Integer roleId) { return roleDAO.queryRoleUsers(roleId); } public User queryUserByName(String name) { User user = null; try { user = userCaches.get(name); if (user.getName() == null) { user = null; } } catch (ExecutionException e) { // logger.error(e.getMessage()); } if (user == null) { user = new User(); user.setName(name); try { userDAO.save(user); } catch (Throwable e) { } user = userDAO.queryByName(name); userCaches.refresh(name); } return user; } public User queryUserAllInfo(String name) { User user = queryUserByName(name); if (user == null) { return null; } user.setPermissions(queryUserPermissionKeys(user.getId()).keySet()); user.setRoles(queryUserRoles(user.getId())); return user; } public User createUser(String name) { User user = userDAO.queryByName(name); if (user != null) { return user; } user = new User(); user.setName(name); userDAO.save(user); return userDAO.queryByName(name); } public Role createRole(String name, String desc) { Role role = roleDAO.queryByName(name); if (role != null) { return role; } role = new Role(); role.setName(name); role.setDescription(desc); roleDAO.save(role); return roleDAO.queryByName(name); } /** * ��ѯ�û�Ȩ�ޣ��û��ӽ�ɫ�̳й�����Ȩ��Ҳ���������֡���Դ����source˵���и��� * * @param userId * @return */ public List<Permission> queryUserPermissions(Integer userId) { try { return userPermissions.get(userId); } catch (ExecutionException e) { return Collections.emptyList(); } } public Map<String, Permission> queryUserPermissionKeys(Integer userId) { List<Permission> permissions = queryUserPermissions(userId); Map<String, Permission> permission = new HashMap<String, Permission>(); for (Permission perm : permissions) { permission.put(perm.getKey(), perm); } return permission; } public Map<String, Permission> queryUserPermissionKeys(String authName) { User user = queryUserByName(authName); if (user != null) { return queryUserPermissionKeys(user.getId()); } return Collections.emptyMap(); } public List<Role> queryUserRoles(Integer userId) { List<Integer> roles = userDAO.queryUserRoles(userId); return roleDAO.queryByIds(roles); } public PaginationResult<Permission> queryPermissions(int pageNumber) { PaginationResult<Permission> result = new PaginationResult<Permission>(pageNumber, 10); result.setTotalSize(permissionDAO.queryCount()); result.setModule(permissionDAO.queryPages(result.getStart(), result.getPageSize())); return result; } public PaginationResult<User> queryUsers(int pageNumber) { PaginationResult<User> result = new PaginationResult<User>(pageNumber, 10); result.setTotalSize(userDAO.queryCount()); result.setModule(userDAO.queryAll(result.getStart(), result.getPageSize())); return result; } public PaginationResult<Role> queryRoles(int pageNumber) { PaginationResult<Role> result = new PaginationResult<Role>(pageNumber, 10); result.setTotalSize(roleDAO.queryCount()); result.setModule(roleDAO.queryAll(result.getStart(), result.getPageSize())); return result; } public void initSecurity(HttpServletRequest request) { String name = (String) request.getAttribute("authName"); if (name == null) { return; } User user = queryUserAllInfo(name); ThreadContext.getContext().putContext("authUser", user); } public LoadingCache<String, User> userCaches = CacheBuilder.newBuilder().maximumSize(100).expireAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader<String, User>() { public User load(String name) throws Exception { User user = userDAO.queryByName(name); if (user == null) { user = new User();// �յ��û� } return user; } }); public LoadingCache<Integer, List<Permission>> userPermissions = CacheBuilder.newBuilder().maximumSize(100).expireAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader<Integer, List<Permission>>() { public List<Permission> load(Integer userId) throws Exception { User user = userDAO.queryById(userId); if (user == null) { return Collections.emptyList();// } Set<Integer> permissionIds = new HashSet<Integer>(); List<Integer> userRoles = userDAO.queryUserRoles(user.getId()); List<Integer> rolePermissions = new ArrayList<Integer>(); if (!userRoles.isEmpty()) { rolePermissions = roleDAO.queryRolesPermissions(userRoles); permissionIds.addAll(rolePermissions); } List<Integer> userPermissions = userDAO.queryUserPermissions(user.getId()); permissionIds.addAll(userPermissions); List<Permission> permissions = permissionDAO.queryByIds(new ArrayList<Integer>(permissionIds)); for (Permission permission : permissions) { if (rolePermissions.contains(permission.getId())) { permission.setDescription(permission.getDescription() + ";���Խ�ɫ��Ȩ��"); } if (userPermissions.contains(permission.getId())) { permission.setDescription(permission.getDescription() + ";�����û���Ȩ��"); } } return permissions; } }); private static volatile boolean modified = false; Thread syncThread = new Thread(new Runnable() { public void run() { while (true) { try { if (modified) { for (String key : securities.keySet()) { regist(key, "ϵͳͬ��"); } modified = false; } Thread.sleep(3000); } catch (Throwable e) { } } } }); @PostConstruct public void init() { syncThread.start(); } public static void check(String[] roles, String[] users, String[] perms) { User user = (User) ThreadContext.getContext().getContext("authUser"); if (user == null) { throw new SecurityException("û���û�����"); } if (roles != null && roles.length > 0) { for (String r : roles) { if (user.getRoleNames().contains(r)) { return; } } } if (users != null && users.length > 0) { for (String r : users) { if (user.getRoleNames().contains(r)) { return; } } } if (perms != null && perms.length > 0) { Set<String> userPermissions = user.getPermissions(); for (String p : perms) { if (!userPermissions.contains(p)) { throw new SecurityException("no permission " + p); } } } } }