봄 보안 권한 관리
AccessDecisionManager
spring security 는 Access Decision Manager 를 통 해 권한 수여 관 리 를 하 는 것 입 니 다.먼저 공식 도 진 루 를 하 겠 습 니 다.
AccessDecisionManager
AccessDecisionManager 인 터 페 이 스 는 다음 과 같은 방법 을 정의 합 니 다.
// AccessDecisionVoter ( )
void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
InsufficientAuthenticationException;
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
다음은 그 실현 류 의 구체 적 인 실현 을 살 펴 보 자.AffirmativeBased
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
int deny = 0;
for (AccessDecisionVoter voter : getDecisionVoters()) {
// AccessDecisionVoter vote( ), vote 。
int result = voter.vote(authentication, object, configAttributes);
if (logger.isDebugEnabled()) {
logger.debug("Voter: " + voter + ", returned: " + result);
}
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:// 1
// voter ACCESS_GRANTED,
return;
case AccessDecisionVoter.ACCESS_DENIED:// -1
deny++;
break;
default:
break;
}
}
if (deny > 0) {
// AccessDecisionVoter( ) ACCESS_DENIED,
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied", "Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
위의 코드 를 통 해 Affirmative Based 정책 을 직접 볼 수 있 습 니 다.
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> attributes) throws AccessDeniedException {
int grant = 0;
int abstain = 0;
List<ConfigAttribute> singleAttributeList = new ArrayList<ConfigAttribute>(1);
singleAttributeList.add(null);
for (ConfigAttribute attribute : attributes) {
singleAttributeList.set(0, attribute);
for (AccessDecisionVoter voter : getDecisionVoters()) {
//
int result = voter.vote(authentication, object, singleAttributeList);
if (logger.isDebugEnabled()) {
logger.debug("Voter: " + voter + ", returned: " + result);
}
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
//
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
default:
abstain++;
break;
}
}
}
// To get this far, there were no deny votes
if (grant > 0) {
// ,
return;
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
이 를 통 해 알 수 있 듯 이 Unanimous Based 정책:
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
int grant = 0;
int deny = 0;
int abstain = 0;
for (AccessDecisionVoter voter : getDecisionVoters()) {
//
int result = voter.vote(authentication, object, configAttributes);
if (logger.isDebugEnabled()) {
logger.debug("Voter: " + voter + ", returned: " + result);
}
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
grant++;
break;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
abstain++;
break;
}
}
if (grant > deny) {
//
return;
}
if (deny > grant) {
//
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied", "Access is denied"));
}
if ((grant == deny) && (grant != 0)) {
//this.allowIfEqualGrantedDeniedDecisions true
// , allowIfEqualGrantedDeniedDecisions
if (this.allowIfEqualGrantedDeniedDecisions) {
return;
}
else {
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied", "Access is denied"));
}
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
이 를 통 해 알 수 있 듯 이 Consensus Based 의 전략:4.567917.통 과 된 표 가 반대 표 보다 많 으 면 통과 로 판결 된다4.567917.통 과 된 표 가 반대 표 보다 적 으 면 통과 되 지 않 는 다
투표 자
이상 의 AccessDecisionManager 의 실현 클래스 는 권한(투표)에 대한 관리(전략의 실현)일 뿐 구체 적 인 투표(vote)의 논 리 는 AccessDecisionVoter 의 하위 클래스(투표 자)를 호출 하 는 vote 방법 을 통 해 이 루어 진다.spring security 는 기본적으로 RoleVoter 와 Authenticated Voter 두 투표 자 를 등록 했다.다음은 그 소스 코드 를 살 펴 보 겠 습 니 다.
AccessDecisionManager
boolean supports(ConfigAttribute attribute);
boolean supports(Class<?> clazz);
// , AccessDecisionManager , 。
int vote(Authentication authentication, S object,
Collection<ConfigAttribute> attributes);
RoleVoter
private String rolePrefix = "ROLE_";
// ROLE_ ( rolePrefix )
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& attribute.getAttribute().startsWith(getRolePrefix())) {
return true;
}
else {
return false;
}
}
public int vote(Authentication authentication, Object object,
Collection<ConfigAttribute> attributes) {
if(authentication == null) {
// ,
return ACCESS_DENIED;
}
int result = ACCESS_ABSTAIN;
//
Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication);
for (ConfigAttribute attribute : attributes) {
if (this.supports(attribute)) {
result = ACCESS_DENIED;
// Attempt to find a matching granted authority
for (GrantedAuthority authority : authorities) {
if (attribute.getAttribute().equals(authority.getAuthority())) {
//
return ACCESS_GRANTED;
}
}
}
}
// , , , , (ACCESS_ABSTAIN)。
return result;
}
간단 하 죠?동시에 우 리 는 AccessDecisionManager 를 실현 함으로써 자신의 voter 를 확장 할 수 있 습 니 다.그러나 이 를 실현 하려 면 attributes 라 는 매개 변수 가 어디서 났 는 지 알 아야 합 니 다.이것 은 매우 관건 적 인 매개 변수 입 니 다.공식 그림 을 통 해 이 문 제 를 뚜렷하게 알 수 있다.다음은 AccessDecisionManager 의 호출 자 Abstract Security Interceptor 를 살 펴 보 자.
AbstractSecurityInterceptor
...
// AffirmativeBased,
private AccessDecisionManager accessDecisionManager;
...
protected InterceptorStatusToken beforeInvocation(Object object) {
...
// , , ConfigAttribute SecurityMetadataSource( , DefaultFilterInvocationSecurityMetadataSource) 。
Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource()
.getAttributes(object);
...
//
Authentication authenticated = authenticateIfRequired();
try {
// AccessDecisionManager
this.accessDecisionManager.decide(authenticated, object, attributes);
}
catch (AccessDeniedException accessDeniedException) {
publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated,
accessDeniedException));
throw accessDeniedException;
}
...
}
public abstract SecurityMetadataSource obtainSecurityMetadataSource();
이상 의 방법 은 모두 AbstractSecurity Interceptor 의 하위 클래스(기본 값 은 FilterSecurity Interceptor)에서 호출 되 었 습 니 다.다시 보 겠 습 니 다.FilterSecurityInterceptor
...
//SecurityMetadataSource , , 。 SecurityMetadataSource ConfigAttribute
private FilterInvocationSecurityMetadataSource securityMetadataSource;
...
//
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
//
invoke(fi);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
if ((fi.getRequest() != null)
&& (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
&& observeOncePerRequest) {
// filter already applied to this request and user wants us to observe
// once-per-request handling, so don't re-do security checking
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
}
else {
// first time this request being called, so perform security checking
if (fi.getRequest() != null) {
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
// (AbstractSecurityInterceptor) , accessDecisionManager
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
}
finally {
super.finallyInvocation(token);
}
// ( ), ,AOP
super.afterInvocation(token, null);
}
}
자,이제 Spring Security 의 권한 관리 에 대해 잘 알 것 같 습 니 다.이것 을 보고 당신 이 원 하 는 권한 수 요 를 확장 할 수 있 을 지 모 르 겠 습 니 다.아직 잘 모 르 겠 으 면 괜 찮 습 니 다.다음 편 은 실전 을 통 해 자신의 권한 체 계 를 개발 하 겠 습 니 다.이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.