package com.tianbo.warehouse.security; import com.tianbo.warehouse.dao.PERMISSIONMapper; import com.tianbo.warehouse.model.PERMISSION; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import org.springframework.util.AntPathMatcher; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * 本类的主要功能就是通过当前的请求地址,获取该地址需要的用户角色 * 如果getAttributes(Object o)方法返回null的话,意味着当前这个请求不需要任何角色就能访问,甚至不需要登录。 */ @Service public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource{ @Autowired PERMISSIONMapper permissionMapper; AntPathMatcher pathMatcher = new AntPathMatcher(); private HashMap<String, Collection<ConfigAttribute>> map =null; /** * 加载权限表中所有权限,还是加载URL所需要的权限 */ public void loadResourceDefine(String requestUrl){ map = new HashMap<>(); Collection<ConfigAttribute> array; ConfigAttribute cfg; List<PERMISSION> permissions = permissionMapper.findAll(); for(PERMISSION permission : permissions) { array = new ArrayList<>(); //此处只添加了用户的名字,其实还可以添加更多权限的信息, // 例如请求方法到ConfigAttribute的集合中去。 // 此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。 //CFG存储访问的URL需要的权限"ROLE_??"LIST String pUrl = permission.getUrl(); List<String> urlOfRoles = permissionMapper.findRoleListByUrl(pUrl); //路径适配,这个很重要,是配上后会包含其他适配的所有权限,比如/**与/user/List是可以适配上的, // 那么/**这个通用适配是要有/user/list这个路径所对应的角色信息的 if(pathMatcher.match(pUrl,requestUrl)){ } for (String roleName:urlOfRoles) { if(null!=roleName) { cfg = new SecurityConfig(roleName); array.add(cfg); } } //用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value, map.put(pUrl, array); } } /** * 所有的权限表中的url所对应的角色信息 * @return 有就返回集合 没有就返回null */ public Collection<ConfigAttribute> loadResourceDefine(){ Collection<ConfigAttribute> array; ConfigAttribute cfg; List<PERMISSION> permissions = permissionMapper.findAll(); for(PERMISSION permission : permissions) { array = new ArrayList<>(); //此处只添加了用户的名字,其实还可以添加更多权限的信息, // 例如请求方法到ConfigAttribute的集合中去。 // 此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。 //CFG存储访问的URL需要的权限"ROLE_??"LIST String pUrl = permission.getUrl(); List<String> urlOfRoles = permissionMapper.findRoleListByUrl(pUrl); for (String roleName:urlOfRoles) { if(null!=roleName) { cfg = new SecurityConfig(roleName); array.add(cfg); } } return array; } return null; } /** * 此方法是为了判定用户请求的url权限 是否有对应的角色, * 如果有对应角色信息,则返回给 decide 方法, * 用来判定用户是否有此权限。如果不在权限表中则放行。 * 如果getAttributes(Object o)方法返回null的话,意味着当前这个请求不需要任何角色就能访问 * getAttributes(Object o)方法返回的集合最终会来到AccessDecisionManager类中 * @param object * @return * @throws IllegalArgumentException */ @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { //清楚地址 String requestUrl = ((FilterInvocation)object).getRequest().getRequestURI(); //每次判定的时候都加载权限对应URL表 // if(map ==null) { loadResourceDefine(requestUrl); // } //object 中包含用户请求的request 信息 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); String resUrl; for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) { resUrl = iter.next(); AntPathRequestMatcher matcher = new AntPathRequestMatcher(resUrl); if(matcher.matches(request)) { return map.get(resUrl); } } return null; } /** * * @return 所有URL对应的所有权限 */ @Override public Collection<ConfigAttribute> getAllConfigAttributes() { // return loadResourceDefine(); return null; } @Override public boolean supports(Class<?> clazz) { return true; } }