MyInvocationSecurityMetadataSourceService.java 5.5 KB
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;
    }
}