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

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

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

背景描述

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

表設(shè)計

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

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 )

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

實現(xiàn)前分析

我們可以逆向思考:

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

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

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

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

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

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

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

項目實戰(zhàn)

1.自定義GrantedAuthority實現(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.自定義認證用戶實例

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實現(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實現(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實現(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,則默認為所有方法都支持
        String httpMethod = StringUtils.isNotBlank(urlGrantedAuthority.getHttpMethod()) ? urlGrantedAuthority.getHttpMethod()
            : urlConfigAttribute.getHttpServletRequest().getMethod();
        //用Spring已經(jīng)實現(xiàn)的AntPathRequestMatcher進行匹配,這樣我們數(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實現(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)限控制之旅吧。

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

相關(guān)文章

  • 解讀為什么不推薦使用keySet()進行遍歷HashMap

    解讀為什么不推薦使用keySet()進行遍歷HashMap

    這篇文章主要介紹了我為什么不推薦使用keySet()進行遍歷HashMap的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • 一文帶你搞懂Java類加載機制

    一文帶你搞懂Java類加載機制

    Java?類加載機制是?Java?運行時的核心組成部分,負責(zé)在程序運行過程中動態(tài)加載和連接類文件,并將其轉(zhuǎn)換為可執(zhí)行代碼,接下來小編就來帶大家搞懂面試官老問的?Java?類加載機制,需要的朋友可以參考下
    2023-08-08
  • Java并發(fā)編程中的ReentrantLock類詳解

    Java并發(fā)編程中的ReentrantLock類詳解

    這篇文章主要介紹了Java并發(fā)編程中的ReentrantLock類詳解,ReentrantLock是juc.locks包中的一個獨占式可重入鎖,相比synchronized,它可以創(chuàng)建多個條件等待隊列,還支持公平/非公平鎖、可中斷、超時、輪詢等特性,需要的朋友可以參考下
    2023-12-12
  • springboot如何獲取請求者的ip地址

    springboot如何獲取請求者的ip地址

    在Spring框架中,可以使用攔截器(Interceptor)來監(jiān)聽每個控制器(Controller)的請求,并記錄請求者的IP地址,這篇文章主要介紹了springboot如何獲取請求者的ip地址,需要的朋友可以參考下
    2024-07-07
  • Java動態(tài)代理分析及簡單實例

    Java動態(tài)代理分析及簡單實例

    這篇文章主要介紹了 Java動態(tài)代理分析及簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Mybatis千萬級數(shù)據(jù)查詢的解決方式,避免OOM問題

    Mybatis千萬級數(shù)據(jù)查詢的解決方式,避免OOM問題

    這篇文章主要介紹了Mybatis千萬級數(shù)據(jù)查詢的解決方式,避免OOM問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • java判斷某個點是否在所畫多邊形/圓形內(nèi)

    java判斷某個點是否在所畫多邊形/圓形內(nèi)

    這篇文章主要為大家詳細介紹了java判斷某個點是否在所畫多邊形或圓形內(nèi)的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • spring中EventListener的使用方式

    spring中EventListener的使用方式

    這篇文章主要介紹了spring中EventListener的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java 事務(wù)詳解及簡單應(yīng)用實例

    Java 事務(wù)詳解及簡單應(yīng)用實例

    這篇文章主要介紹了Java 事務(wù)詳解及簡單應(yīng)用實例的相關(guān)資料,java事務(wù)能夠保證數(shù)據(jù)的完整性和一致性,當(dāng)然這是書本上的知識,具體如何應(yīng)用這里舉例說明,需要的朋友可以參考下
    2016-12-12
  • Springboot中登錄后關(guān)于cookie和session攔截問題的案例分析

    Springboot中登錄后關(guān)于cookie和session攔截問題的案例分析

    這篇文章主要介紹了Springboot中登錄后關(guān)于cookie和session攔截案例,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08

最新評論