成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring Secutity 自定義權(quán)限配置

animabear / 2048人閱讀

摘要:實(shí)現(xiàn)了接口,用于存放用戶信息與權(quán)限在身份認(rèn)證中的作用中進(jìn)行身份驗(yàn)證的是接口,是它的一個(gè)默認(rèn)實(shí)現(xiàn),但它并不用來(lái)處理身份認(rèn)證,而是委托給配置好的,每個(gè)會(huì)輪流檢查身份認(rèn)證。檢查后或者返回對(duì)象或者拋出異常。另外自定義接口,實(shí)現(xiàn)類為。

Srping Security網(wǎng)上也有很多例子,但基本都是所資源直接配置在XML文件里,限制太大,不夠靈活。我們需要的是可以在后臺(tái)修改資源訪問權(quán)限,實(shí)時(shí)生效,才能符合現(xiàn)在大多數(shù)系統(tǒng)的需求。

需要引入的依賴
    
    
        org.springframework.security
        spring-security-web
        4.2.2.RELEASE
    
    
        org.springframework.security
        spring-security-config
        4.2.2.RELEASE
    
    
用戶身份認(rèn)證

我們自定義一個(gè)實(shí)現(xiàn)類MUserDetailsService 來(lái)實(shí)現(xiàn)UserDetailsService接口。

其中需要實(shí)現(xiàn)一個(gè)loadUserByUsername方法,用來(lái)讀取用戶的角色。
在這里需要從數(shù)據(jù)庫(kù)中通過(guò)用戶名來(lái)查詢用戶的信息和用戶所屬的角色
其中MGrantedAuthority實(shí)現(xiàn)了GrantedAuthority接口,用于構(gòu)建用戶權(quán)限。
MUserDeatils實(shí)現(xiàn)了UserDeatils接口,用于存放用戶信息與權(quán)限

UserDetailsService在身份認(rèn)證中的作用

Spring Security中進(jìn)行身份驗(yàn)證的是AuthenticationManager接口,ProviderManager是它的一個(gè)默認(rèn)實(shí)現(xiàn),但它并不用來(lái)處理身份認(rèn)證,而是委托給配置好的AuthenticationProvider,每個(gè)AuthenticationProvider會(huì)輪流檢查身份認(rèn)證。檢查后或者返回Authentication對(duì)象或者拋出異常。驗(yàn)證身份就是加載響應(yīng)的UserDetails,看看是否和用戶輸入的賬號(hào)、密碼、權(quán)限等信息匹配。此步驟由實(shí)現(xiàn)AuthenticationProvider的DaoAuthenticationProvider(它利用UserDetailsService驗(yàn)證用戶名、密碼和授權(quán))處理。包含 GrantedAuthority 的 UserDetails對(duì)象在構(gòu)建 Authentication對(duì)象時(shí)填入數(shù)據(jù)。

MUserDetailsService.class中的loadUserByUsername方法
    /**
     * 根據(jù)用戶名加載用戶密碼與權(quán)限信息
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //查詢用戶信息
        User user = userMapper.selectByName(username);
        List roleList = null;
        MUserDeatils userDeatils = null;
        if (user != null){
            //查詢用戶的角色
            roleList = roleMapper.queryByUser(user.getId());
            System.out.println("user" + user.getUsername() + "----" + user.getPassword());
            // 構(gòu)建權(quán)限
            Set authorities = new HashSet();
            if (roleList.size() != 0){
                for (Role role: roleList){
                    authorities.add(new MGrantedAuthority(role.getName()));
                    System.out.println(role.getName());
                }
                userDeatils = new MUserDeatils(user.getUsername(),user.getPassword(),authorities);

            }
        }
        return userDeatils;

    }
MGrantedAuthority.class
public class MGrantedAuthority implements GrantedAuthority {

    private String authority;

    public MGrantedAuthority(String authority){
        this.authority = authority;
    }

    @Override
    public String getAuthority() {
        return authority;
    }
}
MUserDeatils.class

實(shí)現(xiàn)UserDetails接口定義好變量即可

讀取資源與所屬角色

需要自定義實(shí)現(xiàn)類實(shí)現(xiàn)FilterInvocationSecurityMetadataSource接口。通過(guò)loadResourceDefine方法可以實(shí)現(xiàn)資源與權(quán)限的對(duì)應(yīng)關(guān)系。

要使我們自定義的MFilterInvocationSecurityMetadataSource生效,我們還需要定義一個(gè)MyFilterSecurityInterceptor類。
這里的數(shù)據(jù)需要從數(shù)據(jù)庫(kù)中取得。另外自定義接口UrlMatcher,實(shí)現(xiàn)類為AntUrlPathMatcher。

網(wǎng)上有教程是把loadResourceDefine方法放在了構(gòu)造函數(shù)里。但我經(jīng)過(guò)多次試驗(yàn)均出現(xiàn)service,mapper無(wú)法注入的問題,然后就會(huì)報(bào)一個(gè)空指針的導(dǎo)異常,經(jīng)debug發(fā)現(xiàn)是service沒有注入。經(jīng)多次查詢得知:原因是構(gòu)造方法會(huì)先于注入執(zhí)行,所以loadResourceDefine方法放入構(gòu)造中執(zhí)行時(shí)函數(shù)內(nèi)的service與mapper還未執(zhí)行注入,因此報(bào) java.lang.NullPointerException的異常。解決方法是將loadResourceDefine方法放在getAttributes方法中執(zhí)行。

MFilterInvocationSecurityMetadataSource.class
    @Component
    public class MFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    @Autowired
    public IRescAndRoleService iRescAndRoleService ;
    @Autowired
    private IUserService iUserService ;
    private UrlMatcher urlMatcher = new AntUrlPathMatcher();
    // 資源權(quán)限集合
    private static Map> resourceMap = null;
    public void loadResourceDefine(){
        resourceMap = new HashMap>();
        //取得用戶信息
        List userList = iUserService.query();
       //取得資源與角色列表
        List resourceList = iRescAndRoleService.query();
        System.out.println(resourceList);
        for (RescAndRole resource : resourceList) {
            Collection atts = new ArrayList();
            atts.add(new SecurityConfig(resource.getRoleName() ));
            resourceMap.put(resource.getResString(), atts);
        }
    }
    @Override
    public Collection getAttributes(Object o) throws IllegalArgumentException {
        loadResourceDefine();//防止無(wú)法注入問題
        // guess object is a URL.
        String url = ((FilterInvocation) o).getRequestUrl();
        Iterator ite = resourceMap.keySet().iterator();
        while (ite.hasNext()) {
            String resURL = ite.next();
            if (urlMatcher.pathMatchesUrl(resURL, url)) {
                return resourceMap.get(resURL);
            }
        }
        return null;
    }
    @Override
    public Collection getAllConfigAttributes() {
        return null;
    }
    @Override
    public boolean supports(Class aClass) {
        return true;
    }
}
AntUrlPathMatcher.class
public class AntUrlPathMatcher implements UrlMatcher {

    private boolean requiresLowerCaseUrl;
    private PathMatcher pathMatcher;

    public AntUrlPathMatcher() {
        this(true);
    }

    public AntUrlPathMatcher(boolean requiresLowerCaseUrl) {
        this.requiresLowerCaseUrl = true;
        this.pathMatcher = new AntPathMatcher();

        this.requiresLowerCaseUrl = requiresLowerCaseUrl;
    }

    public Object compile(String path) {
        if (this.requiresLowerCaseUrl) {
            return path.toLowerCase();
        }
        return path;
    }

    public void setRequiresLowerCaseUrl(boolean requiresLowerCaseUrl) {
        this.requiresLowerCaseUrl = requiresLowerCaseUrl;
    }

    public boolean pathMatchesUrl(Object path, String url) {
        if (("/**".equals(path)) || ("**".equals(path))) {
            return true;
        }
        return this.pathMatcher.match((String) path, url);
    }

    public String getUniversalMatchPattern() {
        return "/**";
    }

    public boolean requiresLowerCaseUrl() {
        return this.requiresLowerCaseUrl;
    }

    public String toString() {
        return super.getClass().getName() + "[requiresLowerCase=""
                + this.requiresLowerCaseUrl + ""]";
    }
}
MyFilterSecurityInterceptor.class
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor
        implements Filter {
    private FilterInvocationSecurityMetadataSource securityMetadataSource;
    
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        FilterInvocation fi = new FilterInvocation(request, response, chain);
        invoke(fi);
    }

    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
        return this.securityMetadataSource;
    }

    public Class getSecureObjectClass() {
        return FilterInvocation.class;
    }

    public void invoke(FilterInvocation fi) throws IOException,
            ServletException {
        InterceptorStatusToken token = super.beforeInvocation(fi);
        try {
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            super.afterInvocation(token, null);
        }
    }

    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return this.securityMetadataSource;
    }

    public void setSecurityMetadataSource(
            FilterInvocationSecurityMetadataSource newSource) {
        this.securityMetadataSource = newSource;
    }

    public void destroy() {
    }

    public void init(FilterConfig arg0) throws ServletException {
    }

}
決策管理器

自定義一個(gè)決策管理器MyAccessDecisionManager實(shí)現(xiàn)AccessDecisionManager接口。其中的decide方法,決定某一個(gè)用戶是否有權(quán)限訪問某個(gè)url

/* (non-Javadoc)
     * @see org.springframework.security.access.AccessDecisionManager#decide(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection)
     * 該方法決定該權(quán)限是否有權(quán)限訪問該資源,其實(shí)object就是一個(gè)資源的地址,authentication是當(dāng)前用戶的
     * 對(duì)應(yīng)權(quán)限,如果沒登陸就為游客,登陸了就是該用戶對(duì)應(yīng)的權(quán)限
     */
    @Override
    public void decide(Authentication authentication, Object object,
                       Collection configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        if(configAttributes == null) {
            return;
        }
        System.out.println(object.toString()); // object is a URL.
        //所請(qǐng)求的資源擁有的權(quán)限(一個(gè)資源對(duì)多個(gè)權(quán)限)
        Iterator iterator = configAttributes.iterator();
        while(iterator.hasNext()) {
            ConfigAttribute configAttribute = iterator.next();
            //訪問所請(qǐng)求資源所需要的權(quán)限
            String needPermission = configAttribute.getAttribute();
            System.out.println("訪問"+object.toString()+"需要的權(quán)限是:" + needPermission);
            //用戶所擁有的權(quán)限authentication
            Collection authorities = authentication.getAuthorities();
            for(GrantedAuthority ga : authorities) {
                if(needPermission.equals(ga.getAuthority())) {
                    return;
                }
            }
        }
        //沒有權(quán)限
        throw new AccessDeniedException(" 沒有權(quán)限訪問! ");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean supports(Class clazz) {
        // TODO Auto-generated method stub
        return true;
    }
配置XML web.xml

添加Seucrity的過(guò)濾器,將攔截所有資源訪問

注意
    只能配置成 /*
    
    
    
        contextConfigLocation
        
            WEB-INF/config/security.xml
            WEB-INF/config/spring-mybatis.xml
        
    
    
    
    
        springSecurityFilterChain
        org.springframework.web.filter.DelegatingFilterProxy
    
    
        springSecurityFilterChain
        /*
    
spring-security.xml



    
    
    
    
    
    
    
    
    
    
    

        
        
        
        
        
        
        
        

    

    
    
        
        
        
        
        
        
        
    

    
    
        
            
        
    

    
    

    
    

    
    

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67422.html

相關(guān)文章

  • 基于 Spring Session & Spring Security 微服務(wù)權(quán)限控制

    摘要:構(gòu)造函數(shù)的第一個(gè)參數(shù)是對(duì)象,所以可以自定義緩存對(duì)象。在微服務(wù)各個(gè)模塊獲取用戶的這些信息的方法如下略權(quán)限控制啟用基于方法的權(quán)限注解簡(jiǎn)單權(quán)限校驗(yàn)例如,刪除角色的接口,僅允許擁有權(quán)限的用戶訪問。 showImg(https://segmentfault.com/img/remote/1460000019593311); 微服務(wù)架構(gòu) showImg(https://segmentfault.c...

    clasnake 評(píng)論0 收藏0
  • Shiro【授權(quán)、整合Spirng、Shiro過(guò)濾器】

    摘要:表示對(duì)用戶資源進(jìn)行操作,相當(dāng)于,對(duì)所有用戶資源實(shí)例進(jìn)行操作。與整合,實(shí)際上的操作都是通過(guò)過(guò)濾器來(lái)干的。將安全管理器交由工廠來(lái)進(jìn)行管理。在過(guò)濾器鏈中設(shè)置靜態(tài)資源不攔截。 前言 本文主要講解的知識(shí)點(diǎn)有以下: Shiro授權(quán)的方式簡(jiǎn)單介紹 與Spring整合 初始Shiro過(guò)濾器 一、Shiro授權(quán) 上一篇我們已經(jīng)講解了Shiro的認(rèn)證相關(guān)的知識(shí)了,現(xiàn)在我們來(lái)弄Shiro的授權(quán) Shir...

    ralap 評(píng)論0 收藏0
  • Spring Security 進(jìn)階-細(xì)節(jié)總結(jié)

    摘要:但是我們最好不要在里面對(duì)他進(jìn)行處理,而是放到配置的權(quán)限異常來(lái)處理。記得配置登錄認(rèn)證前和過(guò)程中的一些請(qǐng)求不需要身份認(rèn)證。登錄認(rèn)證失敗不能直接拋出錯(cuò)誤,需要向前端響應(yīng)異常。 關(guān)于 Spring Security 的學(xué)習(xí)已經(jīng)告一段落了,剛開始接觸該安全框架感覺很迷茫,總覺得沒有 Shiro 靈活,到后來(lái)的深入學(xué)習(xí)和探究才發(fā)現(xiàn)它非常強(qiáng)大。簡(jiǎn)單快速集成,基本不用寫任何代碼,拓展起來(lái)也非常靈活和強(qiáng)...

    LinkedME2016 評(píng)論0 收藏0
  • 不用 Spring Security 可否?試試這個(gè)小而美的安全框架

    摘要:寫在前面在一款應(yīng)用的整個(gè)生命周期,我們都會(huì)談及該應(yīng)用的數(shù)據(jù)安全問題。用戶的合法性與數(shù)據(jù)的可見性是數(shù)據(jù)安全中非常重要的一部分。 寫在前面 在一款應(yīng)用的整個(gè)生命周期,我們都會(huì)談及該應(yīng)用的數(shù)據(jù)安全問題。用戶的合法性與數(shù)據(jù)的可見性是數(shù)據(jù)安全中非常重要的一部分。但是,一方面,不同的應(yīng)用對(duì)于數(shù)據(jù)的合法性和可見性要求的維度與粒度都有所區(qū)別;另一方面,以當(dāng)前微服務(wù)、多服務(wù)的架構(gòu)方式,如何共享Sessi...

    toddmark 評(píng)論0 收藏0
  • 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開發(fā) 》

    摘要:下一代服務(wù)端開發(fā)下一代服務(wù)端開發(fā)第部門快速開始第章快速開始環(huán)境準(zhǔn)備,,快速上手實(shí)現(xiàn)一個(gè)第章企業(yè)級(jí)服務(wù)開發(fā)從到語(yǔ)言的缺點(diǎn)發(fā)展歷程的缺點(diǎn)為什么是產(chǎn)生的背景解決了哪些問題為什么是的發(fā)展歷程容器的配置地獄是什么從到下一代企業(yè)級(jí)服務(wù)開發(fā)在移動(dòng)開發(fā)領(lǐng)域 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開發(fā) 》 Kotlin + Spring Boot : 下一代 Java...

    springDevBird 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<