Spring Security 에서 어떻게 상급자 가 하급 자의 모든 권한 을 가지 게 합 니까(사례 분석)
송 형 은 전에 비슷 한 글 을 쓴 적 이 있 지만 주로 용법 을 말 했 습 니 다.오늘 은 원 리 를 봅 시다!
본 고 는 현재 Spring Security 5.3.4 를 바탕 으로 분석 하 는데 왜 최신 판 을 강조 합 니까?5.0.11 버 전에 서 는 캐릭터 계승 구성 이 지금 과 다 르 기 때문이다.구 판 의 방안 을 우 리 는 지금 토론 하지 않 고 현재 최신 판 이 어떻게 처리 되 는 지 직접 보 자.
1.캐릭터 계승 사례
우 리 는 먼저 간단 한 권한 사례 를 하나 하 자.
Spring Boot 프로젝트 를 만 들 고 Spring Security 의존 도 를 추가 하 며 두 개의 테스트 사용 자 를 만 듭 니 다.다음 과 같 습 니 다.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("javaboy")
.password("{noop}123").roles("admin")
.and()
.withUser(" ")
.password("{noop}123")
.roles("user");
}
그리고 세 개의 테스트 인 터 페 이 스 를 준비 합 니 다.다음 과 같 습 니 다.
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
@GetMapping("/admin/hello")
public String admin() {
return "admin";
}
@GetMapping("/user/hello")
public String user() {
return "user";
}
}
이 세 개의 테스트 인터페이스,우리 의 계획 은 다음 과 같다.다음 권한 의 차단 규칙 을 설정 합 니 다.Spring Security 의 configure(HttpSecurity http)방법 에서 코드 는 다음 과 같 습 니 다.
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
.anyRequest().authenticated()
.and()
...
...
여기 서 일치 하 는 규칙 은 Ant 스타일 의 경로 일치 부 호 를 사 용 했 습 니 다.Ant 스타일 의 경로 일치 부 호 는 Spring 가족 에서 매우 광범 위 하 게 사용 되 고 일치 하 는 규칙 도 매우 간단 합 니 다.어댑터
속뜻
**
일치 하 는 다 중 경로
*
일치 하 는 경로
?
임의의 단일 문자 일치
위 설정 의 의 미 는:
/admin/**
형식 이 있 으 면 사용 자 는 admin 역할 을 해 야 합 니 다./user/**
형식 이 있 으 면 사용 자 는 user 역할 을 가 져 야 합 니 다.캐릭터 계승 을 사용 하면 이 기능 이 잘 실 현 됩 니 다.저 희 는 Security Config 에 다음 과 같은 코드 를 추가 하여 캐릭터 계승 관 계 를 설정 하면 됩 니 다.
@Bean
RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_admin > ROLE_user");
return hierarchy;
}
설정 할 때 캐릭터 에 수 동 으로 접 두 사 를 붙 여야 합 니 다ROLE_
.위의 설정 은ROLE_admin
자동 으로ROLE_user
권한 을 갖 추고 있 음 을 나타 낸다.다음 에 우 리 는 프로젝트 를 시작 하여 테스트 를 진행한다.
프로젝트 시작 에 성공 한 후,우 리 는 먼저 강남 약간의 비 로 로그 인 합 니 다.
로그 인 성공 후 각각
/hello
,/admin/hello
및/user/hello
세 개의 인 터 페 이 스 를 방문 합 니 다.그 중에서:/hello
로그 인 하면 접근 할 수 있 기 때문에 이 인터페이스 에 성공 했다./admin/hello
admin 신분 이 필요 해서 방문 에 실 패 했 습 니 다./user/hello
user 신분 이 필요 해서 방문 에 성 공 했 습 니 다./user/hello
인 터 페 이 스 를 방문 할 수 있 습 니 다.이것 은 우리 의 캐릭터 계승 설정 에 문제 가 없다 는 것 을 설명 합 니 다!2.원리 분석
이 설정 의 핵심 은 우리 가 Role Hierarchy 인 스 턴 스 를 제공 하 는 것 입 니 다.그래서 우리 의 분석 은 이런 종류 에서 시작 합 니 다.
Role Hierarchy 는 인터페이스 입 니 다.이 인터페이스 에는 방법 이 하나 밖 에 없습니다.
public interface RoleHierarchy {
Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(
Collection<? extends GrantedAuthority> authorities);
}
이 방법 은 authorities 권한 집합 입 니 다.방법 명 으로 볼 때 방법의 반환 값 은 접근 가능 한 권한 집합 입 니 다.간단 한 예 를 들 어 캐릭터 차원 구 조 는
ROLE_A > ROLE_B > ROLE_C
이 라 고 가정 하고 현재 사용자 에 게 직접 분배 하 는 권한 은ROLE_A
이지 만 실제 사용자 가 가 진 권한 은ROLE_A
,ROLE_B
과ROLE_C
가 있다.getReachable Granted Authorities 방법의 목적 은 캐릭터 차원 에 따라 사용자 가 진정 으로 도달 할 수 있 는 캐릭터 를 분석 하 는 것 이다.
Role Hierarchy 인 터 페 이 스 는 두 가지 실현 유형 이 있 는데 다음 과 같다.
이 유형 에서 실제 적 으로 네 가지 방법
setHierarchy
,getReachableGrantedAuthorities
,buildRolesReachableInOneStepMap
과buildRolesReachableInOneOrMoreStepsMap
에 대해 우 리 는 하나씩 분석 했다.먼저 우리 가 처음에 호출 한 setHierarchy 방법 입 니 다.이 방법 은 캐릭터 의 등급 관 계 를 설정 하 는 데 사 용 됩 니 다.
public void setHierarchy(String roleHierarchyStringRepresentation) {
this.roleHierarchyStringRepresentation = roleHierarchyStringRepresentation;
if (logger.isDebugEnabled()) {
logger.debug("setHierarchy() - The following role hierarchy was set: "
+ roleHierarchyStringRepresentation);
}
buildRolesReachableInOneStepMap();
buildRolesReachableInOneOrMoreStepsMap();
}
사용자 가 들 어 오 는 문자열 변 수 는 role Hierarchy String Representation 속성 에 설정 한 다음 buildRolesReachable InOne StepMap 과 buildRolesReachable InOne Ore StepsMap 방법 을 통 해 캐릭터 등급 에 대한 분석 을 완성 합 니 다.buildRolesReachable InOne StepMap 방법 은 캐릭터 관 계 를 한 층 한 층 의 형식 으로 해석 하 는 데 사용 된다.우 리 는 그것 의 소스 코드 를 살 펴 보 자.
private void buildRolesReachableInOneStepMap() {
this.rolesReachableInOneStepMap = new HashMap<>();
for (String line : this.roleHierarchyStringRepresentation.split("
")) {
String[] roles = line.trim().split("\\s+>\\s+");
for (int i = 1; i < roles.length; i++) {
String higherRole = roles[i - 1];
GrantedAuthority lowerRole = new SimpleGrantedAuthority(roles[i]);
Set<GrantedAuthority> rolesReachableInOneStepSet;
if (!this.rolesReachableInOneStepMap.containsKey(higherRole)) {
rolesReachableInOneStepSet = new HashSet<>();
this.rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet);
} else {
rolesReachableInOneStepSet = this.rolesReachableInOneStepMap.get(higherRole);
}
rolesReachableInOneStepSet.add(lowerRole);
}
}
}
먼저,줄 바 꿈 문자 에 따라 사용자 가 설정 한 여러 캐릭터 의 등급 을 분석 하 는 것 을 보 았 습 니 다.이것 은 무슨 뜻 입 니까?우리 앞의 사례 에서 설정 만 했 습 니 다
ROLE_admin > ROLE_user
.만약 에 여러 개의 계승 관 계 를 설정 해 야 한다 면 어떻게 설정 합 니까?여러 개의 상속 관 계 를
로 분리 하면 다음 과 같다ROLE_A > ROLE_B
ROLE_C > ROLE_D
.캐릭터 의 등급 관계 가 연속 적 이면 이렇게 배치 할 수 있 는 경우 도 있다ROLE_A > ROLE_B > ROLE_C > ROLE_D
.그래서 여 기 는 먼저
로 다 층 상속 관 계 를 분리 하여 하나의 배열 을 만 든 다음 에 배열 을 옮 겨 다 닌 다.구체 적 으로 옮 겨 다 니 면서
>
캐릭터 관 계 를 하나의 배열 로 나 눈 다음 에 배열 을 분석 하고 높 은 등급 의 캐릭터 를 key 로 하고 낮은 등급 의 캐릭터 를 value 로 한다.코드 가 비교적 간단 합 니 다.마지막 으로 rolesReachable InOne StepMap 에 저 장 된 등급 관 계 는 다음 과 같 습 니 다.
캐릭터 계승 관 계 를 가정 하면
ROLE_A > ROLE_B
ROLE_C > ROLE_D
ROLE_C > ROLE_E
맵 의 데 이 터 는 다음 과 같다.ROLE_A > ROLE_B > ROLE_C > ROLE_D
맵 의 데 이 터 는 다음 과 같다.다음 buildRolesReachable InOne Ore StepsMap 방법 은 rolesReachable InOne StepMap 집합 을 재해 석 하여 캐릭터 의 계승 관 계 를 평평 하 게 하 는 것 이다.
예 를 들 어 rolesReachable InOne StepMap 에 저 장 된 캐릭터 계승 관 계 는 다음 과 같다.
buildRolesReachable InOneOre StepsMap 방법의 실현 논 리 를 살 펴 보 겠 습 니 다.
private void buildRolesReachableInOneOrMoreStepsMap() {
this.rolesReachableInOneOrMoreStepsMap = new HashMap<>();
for (String roleName : this.rolesReachableInOneStepMap.keySet()) {
Set<GrantedAuthority> rolesToVisitSet = new HashSet<>(this.rolesReachableInOneStepMap.get(roleName));
Set<GrantedAuthority> visitedRolesSet = new HashSet<>();
while (!rolesToVisitSet.isEmpty()) {
GrantedAuthority lowerRole = rolesToVisitSet.iterator().next();
rolesToVisitSet.remove(lowerRole);
if (!visitedRolesSet.add(lowerRole) ||
!this.rolesReachableInOneStepMap.containsKey(lowerRole.getAuthority())) {
continue;
} else if (roleName.equals(lowerRole.getAuthority())) {
throw new CycleInRoleHierarchyException();
}
rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(lowerRole.getAuthority()));
}
this.rolesReachableInOneOrMoreStepsMap.put(roleName, visitedRolesSet);
}
}
이 방법 은 비교적 교묘 하 다.우선 roleName 에 따라 rolesReachable InOne StepMap 에서 대응 하 는 rolesToVisitSet 를 가 져 옵 니 다.이 rolesToVisitSet 은 Set 집합 으로 옮 겨 다 니 며,옮 겨 다 니 는 결 과 를 visited RolesSet 집합 에 추가 합 니 다.rolesReachable InOne StepMap 집합 키 가 이전에 읽 은 lowerRole 을 포함 하지 않 으 면,이 lowerRole 이 전체 캐릭터 시스템 의 최 하층 이 고 직접 continue 라 는 뜻 이다.그렇지 않 으 면 lowerRole 을 rolesReachable InOne StepMap 에 대응 하 는 value 를 꺼 내 서 계속 옮 겨 다 니 세 요.마지막 으로 스 트 리밍 결 과 를 rolesReachable InOne OrMore StepsMap 집합 에 저장 하면 됩 니 다.
이 방법 은 좀 복잡 하 니,젊은이 들 은 스스로 단점 을 만들어 볼 수 있다.
위의 분석 을 보면 젊은이 들 이 발 견 했 을 수도 있 지만 사실은 캐릭터 계승 은 결국 비 겼 다.
우리 가 정의 한 역할 은 등급 이 있 지만 코드 에서 이런 등급 을 평평 하 게 해서 후속 적 인 비교 에 편리 하 다.
마지막 으로 getReachable Granted Authorities 방법 도 있 습 니 다.들 어 오 는 캐릭터 에 따라 잠재 적 으로 포 함 될 수 있 는 캐릭터 를 분석 합 니 다.
public Collection<GrantedAuthority> getReachableGrantedAuthorities(
Collection<? extends GrantedAuthority> authorities) {
if (authorities == null || authorities.isEmpty()) {
return AuthorityUtils.NO_AUTHORITIES;
}
Set<GrantedAuthority> reachableRoles = new HashSet<>();
Set<String> processedNames = new HashSet<>();
for (GrantedAuthority authority : authorities) {
if (authority.getAuthority() == null) {
reachableRoles.add(authority);
continue;
}
if (!processedNames.add(authority.getAuthority())) {
continue;
}
reachableRoles.add(authority);
Set<GrantedAuthority> lowerRoles = this.rolesReachableInOneOrMoreStepsMap.get(authority.getAuthority());
if (lowerRoles == null) {
continue;
}
for (GrantedAuthority role : lowerRoles) {
if (processedNames.add(role.getAuthority())) {
reachableRoles.add(role);
}
}
}
List<GrantedAuthority> reachableRoleList = new ArrayList<>(reachableRoles.size());
reachableRoleList.addAll(reachableRoles);
return reachableRoleList;
}
이 방법의 논 리 는 비교적 직 설 적 이다.바로 rolesReachable InOne OrMore StepsMap 집합 에서 현재 캐릭터 가 진정 으로 방문 할 수 있 는 캐릭터 정 보 를 조회 하 는 것 이다.3.RoleHierarchyVoter
getReachable Granted Authorities 방법 은 Role Hierarchy Voter 투표 기 에서 호출 됩 니 다.
public class RoleHierarchyVoter extends RoleVoter {
private RoleHierarchy roleHierarchy = null;
public RoleHierarchyVoter(RoleHierarchy roleHierarchy) {
Assert.notNull(roleHierarchy, "RoleHierarchy must not be null");
this.roleHierarchy = roleHierarchy;
}
@Override
Collection<? extends GrantedAuthority> extractAuthorities(
Authentication authentication) {
return roleHierarchy.getReachableGrantedAuthorities(authentication
.getAuthorities());
}
}
Spring Security 투표 기 에 대해 서 는 또 다른 이야기 가 될 것 입 니 다.송 형 은 다음 글 에서 어린이 들 과 투표 기와 의사 결정 기 를 공유 할 것 입 니 다~4.소결
스프링 시 큐 리 티 에서 상급자 가 하급 자 에 게 어떻게 모든 권한 을 가 질 수 있 는 지 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 스프링 시 큐 리 티 상급자 가 하급 자 에 게 모든 권한 을 가 진 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 도 많은 지원 을 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.