>  기사  >  Java  >  Java로 사용자 정의된 Spring Security 권한 제어 관리 예제(실용)

Java로 사용자 정의된 Spring Security 권한 제어 관리 예제(실용)

黄舟
黄舟원래의
2017-03-06 10:16:302247검색

이 글은 주로 Java의 사용자 정의 Spring Security 권한 제어 관리 예제를 소개합니다(실습 글). 관심 있는 친구들이 참고할 수 있습니다.

배경 설명

프로젝트는 url + httpmethod와 같이 세부적인 권한 제어를 수행해야 합니다(예: http://www. php.cn/일부 역할은 보기(HTTP GET)만 가능하고 추가, 수정, 삭제(POST, PUT, DELETE) 권한은 없습니다.

테이블 디자인

의심을 피하기 위해 사용할 핵심 필드만 나열하고 나머지는 직접 파악하시기 바랍니다.

1.admin_user 관리자 사용자 테이블, 키 필드(id, role_id).

2.t_role 역할 테이블, 키 필드(id,privilege_id).

3.t_privilege 권한 테이블, 키 필드(id, url, method)

세 테이블의 관계는 더 말할 필요도 없이 한눈에 볼 수 있다. 필드 밖으로.

구현 전 분석

역으로 생각할 수 있습니다.

필요를 실현하기 위해 가장 중요한 단계는 Spring Security의 AccessDecisionManager가 판단하도록 하는 것입니다. 요청된 URL + httpmethod가 데이터베이스의 구성과 일치하는지 여부. 그러나 AccessDecisionManager는 유사한 요구 사항을 가진 관련 투표자를 결정하지 않습니다. 따라서 Voter 구현을 사용자 정의해야 합니다(기본적으로 등록된 AffirmativeBased 전략은 투표자가 ACCESS_GRANTED 투표를 하는 한 통과된 것으로 결정된다는 것입니다. 우리의 필요에 따라). voter 구현 후 주요 매개변수(Collection

단계 요약:

1. voter 구현을 사용자 정의합니다.

2. ConfigAttribute 구현을 사용자 정의합니다.

3. SecurityMetadataSource 구현을 사용자 정의합니다.

4. 인증에는 사용자 인스턴스가 포함됩니다(물론 모든 사람이 이미 이 작업을 수행했어야 함).

5. 🎜>

실전 전투 프로젝트

1. 맞춤형 GrantedAuthority 구현

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 구현


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 구현


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. 🎜>

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;
        //如果数据库的method字段为null,则默认为所有方法都支持
        String httpMethod = StringUtils.isNotBlank(urlGrantedAuthority.getHttpMethod()) ? urlGrantedAuthority.getHttpMethod()
            : urlConfigAttribute.getHttpServletRequest().getMethod();
        //用Spring已经实现的AntPathRequestMatcher进行匹配,这样我们数据库中的url也就支持ant风格的配置了(例如:/xxx/user/**)    
        AntPathRequestMatcher antPathRequestMatcher = new AntPathRequestMatcher(urlGrantedAuthority.getAuthority(), httpMethod);
        if (antPathRequestMatcher.matches(urlConfigAttribute.getHttpServletRequest()))
          return ACCESS_GRANTED;
      }
    }
    return ACCESS_ABSTAIN;
  }
}


6. FilterSecurityInterceptor 구현 사용자 정의

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);
  }
}


구성 파일 키 구성

<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 권한 제어 여정을 즐겨보세요.

위 내용은 Spring Security 권한 제어 관리 예제의 내용을 사용자 정의한 것입니다. (실습편) 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)

를 참고해주세요.
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.