欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java中自定義Spring Security權(quán)限控制管理示例(實(shí)戰(zhàn)篇)

 更新時(shí)間:2017年02月13日 14:09:44   作者:南軻夢(mèng)  
本篇文章主要介紹了java中自定義Spring Security權(quán)限控制管理示例(實(shí)戰(zhàn)篇) ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。

背景描述

項(xiàng)目中需要做細(xì)粒的權(quán)限控制,細(xì)微至url + httpmethod (滿足restful,例如: https://.../xxx/users/1, 某些角色只能查看(HTTP GET), 而無權(quán)進(jìn)行增改刪(POST, PUT, DELETE))。

表設(shè)計(jì)

為避嫌,只列出要用到的關(guān)鍵字段,其余敬請(qǐng)自行腦補(bǔ)。

1.admin_user 管理員用戶表, 關(guān)鍵字段( id, role_id )。

2.t_role 角色表, 關(guān)鍵字段( id, privilege_id )。

3.t_privilege 權(quán)限表, 關(guān)鍵字段( id, url, method )

三個(gè)表的關(guān)聯(lián)關(guān)系就不用多說了吧,看字段一眼就能看出。

實(shí)現(xiàn)前分析

我們可以逆向思考:

要實(shí)現(xiàn)我們的需求,最關(guān)鍵的一步就是讓Spring Security的AccessDecisionManager來判斷所請(qǐng)求的url + httpmethod 是否符合我們數(shù)據(jù)庫中的配置。然而,AccessDecisionManager并沒有來判定類似需求的相關(guān)Voter, 因此,我們需要自定義一個(gè)Voter的實(shí)現(xiàn)(默認(rèn)注冊(cè)的AffirmativeBased的策略是只要有Voter投出ACCESS_GRANTED票,則判定為通過,這也正符合我們的需求)。實(shí)現(xiàn)voter后,有一個(gè)關(guān)鍵參數(shù)(Collection

總結(jié)一下思路步驟:

1.自定義voter實(shí)現(xiàn)。

2.自定義ConfigAttribute實(shí)現(xiàn)。

3.自定義SecurityMetadataSource實(shí)現(xiàn)。

4.Authentication包含用戶實(shí)例(這個(gè)其實(shí)不用說,大家應(yīng)該都已經(jīng)這么做了)。

5.自定義GrantedAuthority實(shí)現(xiàn)。

項(xiàng)目實(shí)戰(zhàn)

1.自定義GrantedAuthority實(shí)現(xiàn)

UrlGrantedAuthority.java

public class UrlGrantedAuthority implements GrantedAuthority {

  private final String httpMethod;

  private final String url;

  public UrlGrantedAuthority(String httpMethod, String url) {
    this.httpMethod = httpMethod;
    this.url = url;
  }

  @Override
  public String getAuthority() {
    return url;
  }

  public String getHttpMethod() {
    return httpMethod;
  }

  public String getUrl() {
    return url;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    UrlGrantedAuthority target = (UrlGrantedAuthority) o;
    if (httpMethod.equals(target.getHttpMethod()) && url.equals(target.getUrl())) return true;
    return false;
  }

  @Override
  public int hashCode() {
    int result = httpMethod != null ? httpMethod.hashCode() : 0;
    result = 31 * result + (url != null ? url.hashCode() : 0);
    return result;
  }
}

2.自定義認(rèn)證用戶實(shí)例

public class SystemUser implements UserDetails {

  private final Admin admin;

  private List<MenuOutput> menuOutputList;

  private final List<GrantedAuthority> grantedAuthorities;

  public SystemUser(Admin admin, List<AdminPrivilege> grantedPrivileges, List<MenuOutput> menuOutputList) {
    this.admin = admin;
    this.grantedAuthorities = grantedPrivileges.stream().map(it -> {
      String method = it.getMethod() != null ? it.getMethod().getLabel() : null;
      return new UrlGrantedAuthority(method, it.getUrl());
    }).collect(Collectors.toList());
    this.menuOutputList = menuOutputList;
  }

  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    return this.grantedAuthorities;
  }

  @Override
  public String getPassword() {
    return admin.getPassword();
  }

  @Override
  public String getUsername() {
    return null;
  }

  @Override
  public boolean isAccountNonExpired() {
    return true;
  }

  @Override
  public boolean isAccountNonLocked() {
    return true;
  }

  @Override
  public boolean isCredentialsNonExpired() {
    return true;
  }

  @Override
  public boolean isEnabled() {
    return true;
  }

  public Long getId() {
    return admin.getId();
  }

  public Admin getAdmin() {
    return admin;
  }

  public List<MenuOutput> getMenuOutputList() {
    return menuOutputList;
  }

  public String getSalt() {
    return admin.getSalt();
  }
}  

3.自定義UrlConfigAttribute實(shí)現(xiàn)

public class UrlConfigAttribute implements ConfigAttribute {

  private final HttpServletRequest httpServletRequest;

  public UrlConfigAttribute(HttpServletRequest httpServletRequest) {
    this.httpServletRequest = httpServletRequest;
  }


  @Override
  public String getAttribute() {
    return null;
  }

  public HttpServletRequest getHttpServletRequest() {
    return httpServletRequest;
  }
}

4.自定義SecurityMetadataSource實(shí)現(xiàn)

public class UrlFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

  @Override
  public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
    final HttpServletRequest request = ((FilterInvocation) object).getRequest();
    Set<ConfigAttribute> allAttributes = new HashSet<>();
    ConfigAttribute configAttribute = new UrlConfigAttribute(request);
    allAttributes.add(configAttribute);
    return allAttributes;
  }

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

  @Override
  public boolean supports(Class<?> clazz) {
    return FilterInvocation.class.isAssignableFrom(clazz);
  }

}

5.自定義voter實(shí)現(xiàn)

public class UrlMatchVoter implements AccessDecisionVoter<Object> {

 
  @Override
  public boolean supports(ConfigAttribute attribute) {
    if (attribute instanceof UrlConfigAttribute) return true;
    return false;
  }

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

  @Override
  public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
    if(authentication == null) {
      return ACCESS_DENIED;
    }
    Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

    for (ConfigAttribute attribute : attributes) {
      if (!(attribute instanceof UrlConfigAttribute)) continue;
      UrlConfigAttribute urlConfigAttribute = (UrlConfigAttribute) attribute;
      for (GrantedAuthority authority : authorities) {
        if (!(authority instanceof UrlGrantedAuthority)) continue;
        UrlGrantedAuthority urlGrantedAuthority = (UrlGrantedAuthority) authority;
        if (StringUtils.isBlank(urlGrantedAuthority.getAuthority())) continue;
        //如果數(shù)據(jù)庫的method字段為null,則默認(rèn)為所有方法都支持
        String httpMethod = StringUtils.isNotBlank(urlGrantedAuthority.getHttpMethod()) ? urlGrantedAuthority.getHttpMethod()
            : urlConfigAttribute.getHttpServletRequest().getMethod();
        //用Spring已經(jīng)實(shí)現(xiàn)的AntPathRequestMatcher進(jìn)行匹配,這樣我們數(shù)據(jù)庫中的url也就支持ant風(fēng)格的配置了(例如:/xxx/user/**)    
        AntPathRequestMatcher antPathRequestMatcher = new AntPathRequestMatcher(urlGrantedAuthority.getAuthority(), httpMethod);
        if (antPathRequestMatcher.matches(urlConfigAttribute.getHttpServletRequest()))
          return ACCESS_GRANTED;
      }
    }
    return ACCESS_ABSTAIN;
  }
}

6.自定義FilterSecurityInterceptor實(shí)現(xiàn)

public class UrlFilterSecurityInterceptor extends FilterSecurityInterceptor {

  public UrlFilterSecurityInterceptor() {
    super();
  }

  @Override
  public void init(FilterConfig arg0) throws ServletException {
    super.init(arg0);
  }

  @Override
  public void destroy() {
    super.destroy();
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    super.doFilter(request, response, chain);
  }

  @Override
  public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
    return super.getSecurityMetadataSource();
  }

  @Override
  public SecurityMetadataSource obtainSecurityMetadataSource() {
    return super.obtainSecurityMetadataSource();
  }

  @Override
  public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
    super.setSecurityMetadataSource(newSource);
  }

  @Override
  public Class<?> getSecureObjectClass() {
    return super.getSecureObjectClass();
  }

  @Override
  public void invoke(FilterInvocation fi) throws IOException, ServletException {
    super.invoke(fi);
  }

  @Override
  public boolean isObserveOncePerRequest() {
    return super.isObserveOncePerRequest();
  }

  @Override
  public void setObserveOncePerRequest(boolean observeOncePerRequest) {
    super.setObserveOncePerRequest(observeOncePerRequest);
  }
}

配置文件關(guān)鍵配置

<security:http>
  ...
  <security:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR" />
</security:http>

<security:authentication-manager alias="authenticationManager">
  <security:authentication-provider ref="daoAuthenticationProvider"/>
</security:authentication-manager>

<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
  <constructor-arg>
    <list>
      <bean id="authenticatedVoter" class="org.springframework.security.access.vote.AuthenticatedVoter" />
      <bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />
      <bean id="urlMatchVoter" class="com.mobisist.app.security.access.voter.UrlMatchVoter" />
    </list>
  </constructor-arg>
</bean>

<bean id="securityMetadataSource" class="com.mobisist.app.security.access.UrlFilterInvocationSecurityMetadataSource" />

<bean id="filterSecurityInterceptor"
   class="com.mobisist.app.security.access.UrlFilterSecurityInterceptor">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="accessDecisionManager" ref="accessDecisionManager"/>
  <property name="securityMetadataSource" ref="securityMetadataSource" />
</bean> 

好啦,接下來享受你的Spring Security權(quán)限控制之旅吧。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談SpringBoot之開啟數(shù)據(jù)庫遷移的FlyWay使用

    淺談SpringBoot之開啟數(shù)據(jù)庫遷移的FlyWay使用

    這篇文章主要介紹了淺談SpringBoot之開啟數(shù)據(jù)庫遷移的FlyWay使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • Maven依賴管理的用法介紹

    Maven依賴管理的用法介紹

    依賴管理是項(xiàng)目管理中非常重要的一環(huán)。幾乎任何項(xiàng)目開發(fā)的時(shí)候需要都需要使用到庫。而這些庫很可能又依賴別的庫,這樣整個(gè)項(xiàng)目的依賴形成了一個(gè)樹狀結(jié)構(gòu),而隨著這個(gè)依賴的樹的延伸和擴(kuò)大,一系列問題就會(huì)隨之產(chǎn)生
    2022-08-08
  • Java實(shí)現(xiàn)整合文件上傳到FastDFS的方法詳細(xì)

    Java實(shí)現(xiàn)整合文件上傳到FastDFS的方法詳細(xì)

    FastDFS是一個(gè)開源的輕量級(jí)分布式文件系統(tǒng),對(duì)文件進(jìn)行管理,功能包括:文件存儲(chǔ)、文件同步、文件上傳、文件下載等,解決了大容量存儲(chǔ)和負(fù)載均衡的問題。本文將提供Java將文件上傳至FastDFS的示例代碼,需要的參考一下
    2022-02-02
  • SpringCloud Zuul網(wǎng)關(guān)功能實(shí)現(xiàn)解析

    SpringCloud Zuul網(wǎng)關(guān)功能實(shí)現(xiàn)解析

    這篇文章主要介紹了SpringCloud Zuul網(wǎng)關(guān)功能實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Java中比較Long類型是否相等代碼示例

    Java中比較Long類型是否相等代碼示例

    在Java編程中l(wèi)ong是一種數(shù)據(jù)類型,用于表示整數(shù)值,下面這篇文章主要給大家介紹了關(guān)于Java中比較Long類型是否相等的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-05-05
  • Java調(diào)用WebService服務(wù)的三種方式總結(jié)

    Java調(diào)用WebService服務(wù)的三種方式總結(jié)

    雖然WebService這個(gè)框架已經(jīng)過時(shí),但是有些公司還在使用,在調(diào)用他們的服務(wù)的時(shí)候就不得不面對(duì)各種問題,本篇文章總結(jié)了最近我調(diào)用?WebService的心路歷程,3種方式可以分別嘗試,需要的朋友可以參考下
    2023-08-08
  • MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法

    MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法

    今天小編就為大家分享一篇關(guān)于MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • jvm調(diào)優(yōu)的幾種場(chǎng)景(小結(jié))

    jvm調(diào)優(yōu)的幾種場(chǎng)景(小結(jié))

    本文主要介紹了jvm調(diào)優(yōu)的幾種場(chǎng)景,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Java輕松實(shí)現(xiàn)在Excel中添加超鏈接功能

    Java輕松實(shí)現(xiàn)在Excel中添加超鏈接功能

    這篇文章主要為大家詳細(xì)介紹了Java如何輕松實(shí)現(xiàn)在Excel中添加超鏈接功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • Java泛型中<?>和<T>的區(qū)別淺析

    Java泛型中<?>和<T>的區(qū)別淺析

    <T>和<?>的區(qū)別 <T>是參數(shù)類型,常常用于泛型類或泛型方法的定義,下面這篇文章主要給大家介紹了關(guān)于Java泛型中<?>和<T>區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12

最新評(píng)論