Spring Security 사용자 권한 부여 실현
11062 단어 안전 하 다.권한 을 부여 하 다spring-security
지난번 에는 사용
Spring Security
과 Angular
이 사용자 인증 을 실현 했다.Spring Security 및 Angular 사용자 인증 실현이번에 저 희 는
Spring Security
의 권한 수여 체 제 를 통 해 사용자 의 권한 수 여 를 실현 합 니 다.실현 은 매우 간단 해서 모두 가 진지 하 게 들 으 면 알 아들 을 수 있다.
이루어지다
권한 설계
프론트 데스크 톱 은 메뉴 의 권한 통 제 를 실 현 했 지만 백 스테이지 인 터 페 이 스 는 아직 보호 되 지 않 았 습 니 다. 사용자 가 로그 인 에 성공 하면 모든 인 터 페 이 스 를 호출 할 수 있 습 니 다.
저 희 는 사용자 가 어떤 메뉴 의 권한 을 가지 고 있 는 지, 배경 에서 해당 메뉴 의 인터페이스 에 만 접근 할 수 있 기 를 바 랍 니 다.
예 를 들 어 사용 자 는 컴퓨터 팀 이 관리 하 는 메뉴 가 있 으 면 컴퓨터 팀 과 관련 된 추가 삭제 검사 인 터 페 이 스 를 방문 할 수 있 지만 다른 인 터 페 이 스 는 접근 할 수 없다.
Spring Security
의 디자인Spring Security
의 디자인 에 따라 사용 자 는 역할 에 대응 하고 역할 은 배경 인터페이스 에 대응 합 니 다.이것 은 아무런 문제 가 없다.예시
한 인터페이스 에 주 해 를 추가 하고 내부 에 권한 표현 식 을 추가 합 니 다.
@GetMapping
@Secured("ROLE_ADMIN")
public List getAll() {
return hostService.getAll();
}
그리고 사용자 에 게
@Secured
의 역할 을 만 듭 니 다.여기 서 저 희 는 사용자 에 게
Spring Security
의 역할 권한 수 여 를 추가 합 니 다. ROLE_ADMIN
방법 상의 getAll
주석 중의 매개 변수 와 일치 하여 이 사용자 가 이 방법 에 접근 할 수 있 는 권한 이 있다 는 것 을 나타 냅 니 다. 이것 이 바로 권한 수여 입 니 다.private UserDetails createUser(User user) {
logger.debug(" ");
List authorities = new ArrayList<>();
logger.debug(" ");
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
logger.debug(" ");
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
모자라다
우수한 안전 프레임 워 크 로 서
@Secured("ROLE_ADMIN")
이렇게 디자인 하 는 것 은 아무런 문제 가 없다. 우 리 는 간단 한 몇 줄 코드 만 있 으 면 인터페이스의 권한 수여 관 리 를 실현 할 수 있다.하지만 우리 의 요구 에 부합 되 지 않 는 다.
Google 은 시스템 에서 사용자 가 다 중 역할 에 대응 할 것 을 요구 합 니 다.
그러나 우리 의 역할 은 동적 설정 을 할 수 있 도록 요구 하 는 것 이다. 오늘 은 시스템 관리자 의 역할 이 있 고 내일 은 교사 의 역할 을 추가 할 수 있다.
사용자 권한 수여 에 있어 서 동적 설정 을 실현 할 수 있 습 니 다. 사용자 의 권한 목록 은
Spring Security
이기 때문에 저 는 데이터 베이스 에서 현재 사용자 의 역할 을 찾 은 다음 List
들 어 갈 수 있 습 니 다.private UserDetails createUser(User user) {
logger.debug(" ");
List authorities = new ArrayList<>();
logger.debug(" ");
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
logger.debug(" ");
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
그러나 인터페이스 단계 에 서 는 동적 설정 을 실현 할 수 없다.여러분 생각해 보 세 요. 주해 에서 요구 하 는 매개 변 수 는 반드시 상수 여야 합 니 다. 우리 가 동적 으로 설정 하고 싶 어도 실현 할 수 없 는 것 입 니까?
@GetMapping
@Secured("ROLE_ADMIN")
public List getAll() {
return hostService.getAll();
}
그래서 우 리 는 설정 의 제한 을 설명 하기 때문에
add
에서 역할 은 정적 이다.재 설계
우리 의 역할 은 동태 적 인 것 이 고
Spring Security
중의 역할 은 정태 적 인 것 이기 때문에 우리 의 역할 을 Spring Security
중의 역할 에 직접 투사 할 수 없고 매 핑 하려 면 우리 시스템 에서 정태 적 인 대상 과 대응 해 야 한다.캐릭터 가 동적 이 야. 이 건 안 돼.근 데 우리 메뉴 는 정적 이 잖 아.
기능 모듈 은 우리 가 개발 한 것 입 니 다. 메뉴 는 이렇게 고정 되 어 있 습 니 다. 사용자 관리, 역할 관리, 시스템 설정 등 이 있 습 니 다. 우리 가 개발 하 는 동안 이미 고정 되 었 습 니 다. 우 리 는 메뉴 결합
Spring Security
을 사용 하여 권한 을 부여 할 수 있 습 니까?이 그림 을 진지 하 게 보고 이 그림 을 이해 하면 너 는 나의 디자인 사상 을 알 게 될 것 이다.
역할 은 동적 입 니 다. 저 는 권한 을 부여 하지 않 고 정적 메뉴 로 권한 을 부여 합 니 다.
정적 메뉴 대응
Spring Security
에서 정적 역할, 캐릭터 가 백 엔 드 인터페이스 에 대응 합 니 다. 이렇게 디자인 하면 사용자 가 어떤 메뉴 의 권한 을 가지 고 있 는 지, 이 메뉴 에 호출 된 해당 인터페이스 권한 만 가지 고 있다 는 구상 을 실현 합 니 다.부호화
디자인 이 다 되 었 으 니 함께 코드 를 쓰 자.
권한 부여 주석 선택
Spring Security
에는 여러 가지 권한 수여 주해 가 있 는데 개인 이 대 비 를 거 친 후에 Spring Security
주 해 를 선택 합 니 다. 왜냐하면 저 는 이 주해 설정 항목 이 사람들 에 게 이해 되 기 쉽다 고 생각 하기 때 문 입 니 다.public @interface Secured {
/**
* Returns the list of security configuration attributes (e.g. ROLE_USER, ROLE_ADMIN).
*
* @return String[] The secure method attributes
*/
public String[]value();
}
캐릭터 를 직접 쓰 는 문자열 배열 을 보 내 면 됩 니 다.
@Secured("ROLE_ADMIN") // `ROLE_ADMIN`
@Secured({"ROLE_ADMIN", "ROLE_TEACHER"}) // `ROLE_ADMIN`、`ROLE_TEACHER`
메모: 이 문자열 은
@Secured
로 시작 해 야 합 니 다. ROLE_
캐릭터 설정 으로 간주 합 니 다. 그렇지 않 으 면 유효 하지 않 습 니 다.주석 사용 하기
Spring Security
기본 값 @Secured
은 권한 부여 주 해 를 차단 하지 않 고 주 해 를 추가 합 니 다 Spring Security
주 해 를 사용 하 는 전역 방법 으로 차단 합 니 다.@EnableGlobalMethodSecurity(securedEnabled = true) // , @Secured
메뉴 캐릭터 맵
메뉴 에 새 필드
@EnableGlobalMethodSecurity
를 만들어 서 시스템 메뉴 가 어떤 역할 에 대응 하 는 지 설명 합 니 다.// Spring Security
@Column(nullable = false)
private String securityRoleName;
모든
@Secured
캐릭터 의 설정 정 보 를 저장 하고 전역 호출 에 사용 할 클래스 를 만 듭 니 다.여 기 는 매 거 진 것 을 사용 할 수 없습니다.
securityRoleName
주석 에서 요구 하 는 것 은 Spring Security
배열 이 어야 합 니 다. 매 거 진 것 이 라면 Spring Security
형식 으로 문자열 정 보 를 얻어 야 합 니 다. 그러나 유감스럽게도 주석 에서 요구 하 는 것 은 상수 여야 합 니 다.지난번 사용자 정의
@Secured
상태 코드 를 사용 할 때 확장 할 수 없 는 손 해 를 입 었 던 것 을 기억 합 니 다. 이후 에는 더 이상 매 거 할 필요 가 없습니다.매 거 진 인 터 페 이 스 를 사용 하 더 라 도 이 인 터 페 이 스 를 매 거 진 실현 할 것 입 니 다. 매 거 진 성명 방법의 매개 변수 유형 을 사용 하지 않 고 인터페이스 성명 을 사용 하여 확장 이 편리 합 니 다.package club.yunzhi.huasoft.security;
/**
* @author zhangxishuo on 2019-03-02
* Yunzhi Security
*
*/
public class YunzhiSecurityRole {
public static final String ROLE_MAIN = "ROLE_MAIN";
public static final String ROLE_HOST = "ROLE_HOST";
public static final String ROLE_GROUP = "ROLE_GROUP";
public static final String ROLE_USER = "ROLE_USER";
public static final String ROLE_ROLE = "ROLE_ROLE";
public static final String ROLE_SETTING = "ROLE_SETTING";
}
예시
@GetMapping
@Secured({YunzhiSecurityRole.ROLE_HOST, YunzhiSecurityRole.ROLE_GROUP})
public List getAll() {
return hostService.getAll();
}
사용자 권한 부여
코드 는 권한 수여 방향 을 나타 낸다. 현재 사용자 의 메뉴 를 옮 겨 다 니 며 메뉴 에 대응 하 는
String
캐릭터 이름 에 따라 권한 을 부여 한다.private UserDetails createUser(User user) {
logger.debug(" ");
Set menus = webAppMenuService.getAllAuthMenuByUser(user);
logger.debug(" ");
List authorities = new ArrayList<>();
logger.debug(" , ");
for (WebAppMenu menu : menus) {
authorities.add(new SimpleGrantedAuthority(menu.getSecurityRoleName()));
}
logger.debug(" ");
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
주: 여기 서
YunzhiSecurityRoleEnum.ROLE_MAIN.name()
타성 로드 로 인 한 오류 가 발생 했 습 니 다. 트 랜 잭 션 방지 HTTP
를 사용 하여 닫 기 Security
를 방지 하고 심층 원 리 는 아직 연구 중 입 니 다.유닛 테스트
유닛 테스트 는 매우 간단 하여 같은 기능 을 쓰 는 사람 이 참고 하도록 제공 합 니 다.
@Test
public void authTest() throws Exception {
logger.debug(" ");
WebAppMenu hostMenu = webAppMenuRepository.findByRoute("/host");
WebAppMenu groupMenu = webAppMenuRepository.findByRoute("/group");
WebAppMenu settingMenu = webAppMenuRepository.findByRoute("/setting");
logger.debug(" ");
List roleList = new ArrayList<>();
Role roleHost = new Role();
roleHost.setWebAppMenuList(Collections.singletonList(hostMenu));
roleList.add(roleHost);
Role roleGroup = new Role();
roleGroup.setWebAppMenuList(Collections.singletonList(groupMenu));
roleList.add(roleGroup);
Role roleSetting = new Role();
roleSetting.setWebAppMenuList(Collections.singletonList(settingMenu));
roleList.add(roleSetting);
logger.debug(" ");
roleRepository.saveAll(roleList);
logger.debug(" ");
User user = userService.getOneUnSavedUser();
logger.debug(" ");
String username = user.getUsername();
String password = user.getPassword();
logger.debug(" ");
userRepository.save(user);
logger.debug(" ");
String token = this.loginWithUsernameAndPassword(username, password);
logger.debug(" host, 403");
this.mockMvc.perform(MockMvcRequestBuilders.get(HOST_URL)
.header(TOKEN_KEY, token))
.andExpect(status().isForbidden());
logger.debug(" Host ");
user.getRoleList().clear();
user.getRoleList().add(roleHost);
userRepository.save(user);
logger.debug(" , ");
token = this.loginWithUsernameAndPassword(username, password);
logger.debug(" Host , 200");
this.mockMvc.perform(MockMvcRequestBuilders.get(HOST_URL)
.header(TOKEN_KEY, token))
.andExpect(status().isOk());
logger.debug(" Group ");
user.getRoleList().clear();
user.getRoleList().add(roleGroup);
userRepository.save(user);
logger.debug(" , ");
token = this.loginWithUsernameAndPassword(username, password);
logger.debug(" Group , 200");
this.mockMvc.perform(MockMvcRequestBuilders.get(HOST_URL)
.header(TOKEN_KEY, token))
.andExpect(status().isOk());
logger.debug(" Setting ");
user.getRoleList().clear();
user.getRoleList().add(roleSetting);
userRepository.save(user);
logger.debug(" , ");
token = this.loginWithUsernameAndPassword(username, password);
logger.debug(" Setting , 403");
this.mockMvc.perform(MockMvcRequestBuilders.get(HOST_URL)
.header(TOKEN_KEY, token))
.andExpect(status().isForbidden());
}
private String loginWithUsernameAndPassword(String username, String password) throws Exception {
logger.debug(" ");
byte[] encodedBytes = Base64.encodeBase64((username + ":" + password).getBytes());
MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get(LOGIN_URL)
.header("Authorization", "Basic " + new String(encodedBytes)))
.andExpect(status().isOk())
.andReturn();
logger.debug(" token");
String json = mvcResult.getResponse().getContentAsString();
JSONObject jsonObject = JSON.parseObject(json);
return jsonObject.getString("token");
}
총결산
개원 커 뮤 니 티 감사합니다.
Hibernate
。 다섯 줄 코드 (주석 제외), 주석 하나.그동안 우 리 를 괴 롭 혔 던 권한 문 제 를 해결 했다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Linux sudo 권한 향상 빈틈 CVE - 2021 - 31561 월 26 일 에 Sudo 는 유 닉 스 와 유사 한 운영 체제 가 명령 매개 변수 에서 역 슬 래 쉬 를 피 할 때 쌓 인 버퍼 에 구멍 이 나 지 않도록 안전 통 지 를 발표 했다.빈틈 등급: 고위 험, 빈틈 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.