spring security使用心得

spring security里面的四个重要的类,都需自己去实现:

1、UserDetailsService  读取登录用户信息、权限

2、AbstractSecurityInterceptor 这个类是用来继承的,还要实现servler的Filter,作用过滤url

3、FilterInvocationSecurityMetadataSource  读取url资源

4、AccessDecisionManager 控制访问权限

流程图


以上转载自:http://blog.csdn.net/u011511684/article/details/31394493

以下关于我自己搭建security框架(使用数据库url控制)所遇问题+解决方式

已知decide方法是用来做权限验证的,return 表示成功,进下一个filter。decide方法有三个参数:
@Override
    public void decide(Authentication authentication, Object object,
                       Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
1.authentication:这参数是从userDetailsService类的loadUserByUserName方法中来的:也就是authories
如下图

@Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        SmUser user = null;
        try {
            user = smUserRepository.findByUserIdAndStatus(userName, BaseConstants.USER_STATUS);
        } catch (DataAccessException e) {
            logger.error(e.getMessage());
            throw new UsernameNotFoundException(userName + "not exsit");
        }
        UserDetails userDetails = null;
        //获取权限
        List<GrantedAuthority> authories = new ArrayList<>();
        //查询用户角色对应所有comCode
        List<String> roleComponentList = smComponentService.getComCodeByUserId(user.getUserId());
        for (String roleComponent : roleComponentList) {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(roleComponent);
            /**
             * 之前不好理解的就是authories集合中传什么值,有什么作用
             * 其实就是相当于传一个唯一性标志(url也可以,主键也可以),目的是在重写的MyAccessDecisionManager类中作为权限对比的标志
             */
            authories.add(grantedAuthority);
        }
        if (user != null) {
//            userDetails = new User(user.getUserId(), user.getPassword(), true, true, true, true, authories);
            userDetails = new User(user.getUserId(), user.getPassword(), authories);
        }
        return userDetails;
    }

2.object参数

object参数其实就是输入的html的网址,比如:http如下,

object获取的就是/cdss


3.configAttibutes:

 这个参数哪里来的:为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果

package com.jhmk.earlywaring.auth;

import com.jhmk.earlywaring.entity.RoleComponent;
import com.jhmk.earlywaring.entity.SmComponent;
import com.jhmk.earlywaring.repository.RoleComponentRepository;
import com.jhmk.earlywaring.repository.SmComponentRepository;
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 javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {
    @Autowired
    RoleComponentRepository roleComponentRepository;
    @Autowired
    private SmComponentRepository smComponentRepository;

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

    public void loadResourceDefine() {
        map = new HashMap<>();
        Collection<ConfigAttribute> array;
        ConfigAttribute cfg;

        List<SmComponent> components = smComponentRepository.findAll();
        for (SmComponent c : components) {
            array = new ArrayList<>();
            cfg = new SecurityConfig(c.getComCode());
            array.add(cfg);
            //用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,array:url对应role的list集合
            map.put(c.getComEntry(), array);
        }

    }

    /**
     * 用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,
     *
     * @param o
     * @return
     * @throws IllegalArgumentException
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        if (map == null)
            loadResourceDefine();
        //object 中包含用户请求的request 信息
        HttpServletRequest request = ((FilterInvocation) o).getHttpRequest();
        AntPathRequestMatcher matcher;
        String resUrl;
        Iterator<String> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            resUrl = iterator.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<?> aClass) {
        return true;
    }
}

参数作用:为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。其实用白话说就是他会先执行上图loadResourceDefine这个方法,查询出所有权限放入map中,然后呢,比如刚刚请求的是/cdss这个请求,他会获取/cdss对应的唯一标识(一般是主键,自己决定) ,判断是不是在map中,如果存在,则进行权限验证,不存在,则放过。

package com.jhmk.earlywaring.auth;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Iterator;

@Service
public class MyAccessDecisionManager implements AccessDecisionManager {


    /**
     * // decide 方法是判定是否拥有权限的决策方法,
     * //configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
     *
     * @param authentication   CustomUserService中循环添加到 GrantedAuthority 对象中的权限信息集合.(用户所具有的权限)
     * @param object  包含客户端发起的请求的requset信息,可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
     * @param configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
     * @throws AccessDeniedException
     * @throws InsufficientAuthenticationException
     */


    @Override
    public void decide(Authentication authentication, Object object,
                       Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        // TODO Auto-generated method stub
        System.out.println("MyAccessDescisionManager.decide()------------------验证用户是否具有一定的权限--------");
        if (configAttributes == null) return;
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        if (matchers("/images/**", request)
                || matchers("/js/**", request)
                || matchers("/css/**", request)
                || matchers("/fonts/**", request)
                || matchers("/font/**", request)
                || matchers("/", request)
                || matchers("/login", request)) {
            return;
        } else {
            for (Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
                String needResource = iter.next().getAttribute();
                //authentication.getAuthorities()  用户所有的权限
                for (GrantedAuthority ga : authentication.getAuthorities()) {
                    if (needResource.equals(ga.getAuthority())) {
                        return;
                    }
                }
            }
        }


        throw new AccessDeniedException("--------MyAccessDescisionManager:decide-------对不起,您没有权限登录此界面!");

    }

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

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

    private boolean matchers(String url, HttpServletRequest request) {
        AntPathRequestMatcher matcher = new AntPathRequestMatcher(url);
        if (matcher.matches(request)) {
            return true;
        }
        return false;
    }
}
如果错误,欢迎指正
 

 

 




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值