-
Notifications
You must be signed in to change notification settings - Fork 37
2단계 - 인가(Authorization) 리뷰 요청 드립니다. #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
313c011
7e036b1
c953150
439e1a5
a63a21e
8cdf3dc
21e639b
706c626
0f8d213
0119cca
f87ce1e
83a4efd
eca7352
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package nextstep.security.authorization; | ||
|
||
import nextstep.security.authorization.web.AuthorizationResult; | ||
|
||
public class AuthorizationDecision implements AuthorizationResult { | ||
public static final AuthorizationDecision ALLOW = new AuthorizationDecision(true); | ||
public static final AuthorizationDecision DENY = new AuthorizationDecision(false); | ||
|
||
private final boolean granted; | ||
|
||
public AuthorizationDecision(boolean granted) { | ||
this.granted = granted; | ||
} | ||
|
||
public boolean isGranted() { | ||
return granted; | ||
} | ||
|
||
public static AuthorizationDecision of(boolean granted) { | ||
return granted ? ALLOW : DENY; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package nextstep.security.authorization; | ||
|
||
import nextstep.security.authentication.Authentication; | ||
import nextstep.security.authorization.web.AuthorizationResult; | ||
import nextstep.security.context.SecurityContextHolder; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
|
||
public class AuthorizationFilter extends OncePerRequestFilter { | ||
|
||
private final AuthorizationManager<HttpServletRequest> authorizationManager; | ||
|
||
public AuthorizationFilter(AuthorizationManager<HttpServletRequest> authorizationManager) { | ||
this.authorizationManager = authorizationManager; | ||
} | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) | ||
throws ServletException, IOException { | ||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
AuthorizationResult authorizeResult = authorizationManager.authorize(authentication, request); | ||
|
||
if (!authorizeResult.isGranted()) { | ||
throw new ForbiddenException(); | ||
} | ||
|
||
filterChain.doFilter(request, response); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package nextstep.security.authorization; | ||
|
||
import nextstep.security.authentication.Authentication; | ||
import nextstep.security.authorization.web.AuthorizationResult; | ||
|
||
@FunctionalInterface | ||
public interface AuthorizationManager<T> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 준형님이 생각하시기에 선택사항으로 주어진 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 음.. 결국엔 인가실패시 예외를 발생시킨다. 가 핵심이라고 생각해요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네 사실 다만 실제 |
||
@Deprecated | ||
AuthorizationDecision check(Authentication authentication, T object); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 spring security를 확인해보시면
spring-projects/spring-security#14712 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오.. 불과 4달전에 업데이트된 기능이군요! |
||
|
||
default AuthorizationResult authorize(Authentication authentication, T object) { | ||
return check(authentication, object); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package nextstep.security.authorization.method; | ||
|
||
import java.lang.reflect.Method; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.Set; | ||
import nextstep.security.authentication.Authentication; | ||
import nextstep.security.authorization.AuthorizationDecision; | ||
import nextstep.security.authorization.AuthorizationManager; | ||
import nextstep.security.authorization.Secured; | ||
import nextstep.security.authorization.web.AuthorityAuthorizationManager; | ||
import org.aopalliance.intercept.MethodInvocation; | ||
|
||
public class SecuredAuthorizationManager implements AuthorizationManager<MethodInvocation> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
boolean hasAuthority = authentication.getAuthorities().stream()
.anyMatch(authorities::contains);
return new AuthorizationDecision(hasAuthority); 부분이 동일한 것을 확인해볼 수 있어요. 각 즉, 실제로는 권한체계가 다양하기 때문에 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 83a4efd 현재 말씀해주신 |
||
|
||
private AuthorityAuthorizationManager<Collection<String>> authorityAuthorizationManager; | ||
|
||
public void setAuthorityAuthorizationManager(Collection<String> authorities) { | ||
authorityAuthorizationManager = new AuthorityAuthorizationManager<>(authorities); | ||
} | ||
|
||
@Override | ||
public AuthorizationDecision check(Authentication authentication, MethodInvocation invocation) { | ||
Collection<String> authorities = getAuthorities(invocation); | ||
|
||
if (authorities.isEmpty()) { | ||
return null; | ||
} | ||
setAuthorityAuthorizationManager(authorities); | ||
return authorities.isEmpty() ? null : authorityAuthorizationManager.check(authentication, authorities); | ||
} | ||
|
||
private Collection<String> getAuthorities(MethodInvocation invocation) { | ||
Method method = invocation.getMethod(); | ||
|
||
if (!method.isAnnotationPresent(Secured.class)) { | ||
return Collections.emptySet(); | ||
} | ||
|
||
Secured secured = method.getAnnotation(Secured.class); | ||
return Set.of(secured.value()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package nextstep.security.authorization.web; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import nextstep.security.authentication.Authentication; | ||
import nextstep.security.authorization.AuthorizationDecision; | ||
import nextstep.security.authorization.AuthorizationManager; | ||
|
||
public class AuthenticatedAuthorizationManager implements AuthorizationManager<HttpServletRequest> { | ||
@Override | ||
public AuthorizationDecision check(Authentication authentication, HttpServletRequest object) { | ||
if (authentication != null && authentication.isAuthenticated()) { | ||
return AuthorizationDecision.ALLOW; | ||
} | ||
return AuthorizationDecision.DENY; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package nextstep.security.authorization.web; | ||
|
||
import java.util.Collection; | ||
import nextstep.security.authentication.Authentication; | ||
import nextstep.security.authentication.AuthenticationException; | ||
import nextstep.security.authorization.AuthorizationDecision; | ||
import nextstep.security.authorization.AuthorizationManager; | ||
|
||
public class AuthorityAuthorizationManager<T> implements AuthorizationManager<T> { | ||
|
||
private final Collection<String> authorities; | ||
|
||
public AuthorityAuthorizationManager(Collection<String> authorities) { | ||
this.authorities = authorities; | ||
} | ||
|
||
|
||
@Override | ||
public AuthorizationDecision check(Authentication authentication, T object) { | ||
if (authentication == null) { | ||
throw new AuthenticationException(); | ||
} | ||
|
||
boolean hasAuthority = isAuthorized(authentication, authorities); | ||
|
||
return AuthorizationDecision.of(hasAuthority); | ||
} | ||
|
||
|
||
private boolean isAuthorized(Authentication authentication, Collection<String> authorities) { | ||
for (String authority : authentication.getAuthorities()) { | ||
if (authorities.contains(authority)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package nextstep.security.authorization.web; | ||
|
||
public interface AuthorizationResult { | ||
boolean isGranted(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
관습적으로 정적 팩토리 메소드는 파라미터가 하나일때 from, 여러개일때 of를 활용합니다.