Spring Security 流程

摘要:
首先,创建四个类。过程大致如下:1.容器开始在MyInvocationSecurityMetadataSourceService中加载系统资源和权限列表(HashMap)loadResourceDefine@ServicepublicclassMyInvocationSecurityMetadataSourceServiceimplementsFilterInvocationSecurityMetad

Spring Security 流程第1张

首先创建4个类

流程大致如下:

1、容器启动 加载系统资源与权限列表(HashMap) MyInvocationSecurityMetadataSourceService中的loadResourceDefine

Spring Security 流程第2张Spring Security 流程第3张
@Service
public class MyInvocationSecurityMetadataSourceService  implements
        FilterInvocationSecurityMetadataSource {

    @Autowired
    private PermissionDao permissionDao;

    private HashMap<String, Collection<ConfigAttribute>> map =null;

    /**
     * 加载所有资源与权限的关系
     */
    public void loadResourceDefine(){
        map = new HashMap<>();
        Collection<ConfigAttribute> array;
        ConfigAttribute cfg;
        List<Permission> permissions = permissionDao.findAll();
        for(Permission permission : permissions) {
            array = new ArrayList<>();
            //角色名称
            cfg = new SecurityConfig(permission.getName());
            array.add(cfg);
            map.put(permission.getUrl(), array);
        }


    }

    /**
     *返回请求资源所需要的权限
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        if(map ==null) loadResourceDefine();
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        AntPathRequestMatcher matcher;
        String resUrl;
        for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) {
            resUrl = iter.next();
            matcher = new AntPathRequestMatcher(resUrl);
            if(matcher.matches(request)) {
                return map.get(resUrl);
            }
        }
        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
View Code

2、用户发出请求

3、过滤器拦截 MyFilterSecurityInterceptor中的doFilter()

Spring Security 流程第4张Spring Security 流程第5张
@Service
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
    /**
     * 过滤请求 调用FilterInvocationSecurityMetadataSource 资源和 MyAccessDecisionManager进行验证
     */

    @Autowired
    private FilterInvocationSecurityMetadataSource securityMetadataSource;

    @Autowired
    public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
        super.setAccessDecisionManager(myAccessDecisionManager);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /**
         * FilterInvocation 把doFilter传进来的request、response、chain对象保存起来
         */
        FilterInvocation fi = new FilterInvocation(request, response, chain);
        invoke(fi);
    }
    public void invoke(FilterInvocation fi) throws IOException, ServletException {
        //fi里面有一个被拦截的url
        //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 HashMap中
        //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
        //object为FilterInvocation对象
        //
        //1、获取请求资源的权限
        //执行Collection<ConfigAttribute> attributes=securityMetadataSource.getAttributes(fi);
        //2、是否拥有权限
        //执行 this.accessDecisionManager.decide(authenticated,fi,attributes);
        InterceptorStatusToken token = super.beforeInvocation(fi);
        /**
         * InterceptorStatusToken token = super.beforeInvocation(fi);会调用MyAccessDecisionManager中decide方法
         * 和MyInvocationSecurityMetadataSource中getAttributes方法
         */
        try {
            //执行下一个拦截器
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            super.afterInvocation(token, null);
        }
    }


    @Override
    public void destroy() {

    }

    @Override
    public Class<?> getSecureObjectClass() {
        return FilterInvocation.class;

    }

    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return this.securityMetadataSource;
    }
}
View Code

4、取得请求资源所需权限MyInvocationSecurityMetadataSourceService中getAttributes()

5、匹配用户的权限和请求所需要的权限MyAccessDecisionManager中decide()

Spring Security 流程第6张Spring Security 流程第7张
@Service
public class MyAccessDecisionManager implements AccessDecisionManager {
    /**
     * @param authentication 用户具有的角色权限,认证的入口
     * @param object 当前正在请求的受保护的对象
     * @param configAttributes 受保护对象的配置属性—所具有的权限
     * @throws AccessDeniedException
     * @throws InsufficientAuthenticationException
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        //如果访问资源不需要任何权限则直接通过
        if(null== configAttributes || configAttributes.size() <=0) {
            return;
        }
        ConfigAttribute c;
        String needRole;
        //遍历configAttributes看用户是否有访问资源的权限
        for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
            c = iter.next();
            needRole = c.getAttribute();
            for(GrantedAuthority ga : authentication.getAuthorities()) {
                //ga 用户所被赋予的权限,needRole 访问相应资源应具有的权限
                if(needRole.trim().equals(ga.getAuthority())) {
                    return;
                }
            }
        }
        // 如果访问被拒绝,实现将抛出一个AccessDeniedException异常。
        throw new AccessDeniedException("no right");
    }



    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
View Code

6、登录

Spring Security 流程第8张Spring Security 流程第9张
@Service
public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口

    @Autowired
    UserDao userDao;
    @Autowired
    PermissionDao permissionDao;

    /**
     *点击登录跳转 保存用户权限
     *
     */
    public UserDetails loadUserByUsername(String username) {
        SysUser user = userDao.findByUserName(username);
        if (user != null) {
            List<Permission> permissions = permissionDao.findByAdminUserId(user.getId());
            List<GrantedAuthority> grantedAuthorities = new ArrayList <>();
            for (Permission permission : permissions) {
                if (permission != null && permission.getName()!=null) {
                GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());
                grantedAuthorities.add(grantedAuthority);
                }
            }
            return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
        } else {
            throw new UsernameNotFoundException("admin: " + username + " do not exist!");
        }
    }

}
View Code

7、验证并授权

免责声明:文章转载自《Spring Security 流程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇js判断当前是ios还是androidBootstrap 中visible-xs、hidden-xs等的用法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

关于服务器并发量的简单计算

最简单的计算方式就是根据服务器带宽与页面的大小1.假设机房带宽为10Mbs,页面的大小为20KB同时并发量的理论值:10*1024/=64个请求/秒理论上1秒钟同时可以有64个请求访问页面。本考试系统,登陆的页面容量比较大,所有的js,css以及图片未优化前在400KB左右,我们就以400KB为基准,所有后面要用的文件是在首页一次性加载下来的。这一天的测评情...

sqlite3 数据类型 批量插入

SQLite3采用动态数据类型。存储值的数据类型与值本身相关,而不是由其字段类型决定。SQLite3的动态数据类型可以向后兼容其他数据库常用的静态类型,这意味着在使用静态数据类型的数据库中使用的数据表也可以在SQLite3中使用。在SQLite2数据库中,除了声明为主键的INTEGER列外,任何列都可以存储属于任何存储类型的值。...

Java 安全之:csrf攻击总结

最近,我在维护一些旧项目。在调试期间,我发现请求被反复拒绝。我仔细查看了项目的源代码,发现存在csrftoken验证。我借此机会了解了csrf攻击,并将其总结成一篇论文。受攻击的网站无法阻止攻击。在整个过程中,攻击者无法获取受害者的登录凭据,只能“冒充”。CSRF攻击成功,因为服务器将攻击者发送的请求误认为是用户的请求。服务器通过验证请求是否携带正确的令牌来...

狼人杀规则

自爆后,所有演讲立即暂停,进入夜间。自爆后的那晚,狼人可以指着那把刀。预言家只能验证某个玩家是否是狼人,除狼人是否是狼人之外的所有信息都无法验证。如果先知测试丘比特,法官不必担心丘比特是哪一个阵营,只会展示好人的手势。...

十四、ES开启密码认证

所以我们需要为es head和kibana添加密码认证。4、 为kibana设置密码。1.为kibana配置证书。因为kibana和es之间的连接也需要证书加密通信。mkdir-p/etc/kibana/certscp/etc/selastic search/certs-*/etc/kibana/certs/2.授予kibana主要权限。权限必须为kiban...

可爱猫+python——定制化微信机器人

框架是模拟真实用户操作,只要不违法乱纪,是不用担心账号冻结问题的。...