-
Notifications
You must be signed in to change notification settings - Fork 36
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
๐ ์ ํ - RoleHierarchy ๋ฆฌ๋ทฐ ์์ฒญ ๋๋ฆฝ๋๋ค. #20
Conversation
- ์์๋ก RoleHierarchy ๊ตฌ์กฐ ์ปค๋ฐ
- ์ฌ์ฉ์ Role์ ์ด๋ฆ์ ์ ์ฅํ๊ณ ๋น๊ตํ ์ ์๋ ์ธ๊ฐ ๊ฐ์ฒด ์์ฑ
โฆity>๋ก ๋ณ๊ฒฝ - Authentication ๊ฐ์ฒด๊ฐ ๊ถํ์ String์ด ์๋ GrantedAuthority ๊ฐ์ฒด๋ก ๊ด๋ฆฌํ๋๋ก ๊ฐ์
- MEMBER ๋กค์ ๊ธฐ๋ณธ ๋กค์ผ๋ก ADMIN ์ ๊ฐ์ง๋ฉด MEMBER ๋กค๋ ์ธ๊ฐํ๋ค.
- Update README with optional mission requirements
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.
์๋ ํ์ธ์ ์ธ์ค๋ ๐
์ ํ๋ฏธ์ ๋ ์ ๊ตฌํํด์ฃผ์ จ๋ค์. ๋ช๊ฐ์ง ์ฝ๋ฉํธ ๋จ๊ฒจ๋์์ผ๋ ํ์ธ๋ถํ๋๋ ค์ :)
๊ถ๊ธํ๊ฑฐ๋ ๊ณ ๋ฏผ์ด ๋๋ ๋ถ๋ถ์ด ์์ผ์๋ค๋ฉด ์ธ์ ๋ pr ์ฝ๋ฉํธ ๋๋ dm์ผ๋ก ์์ฒญ ๋ถํ๋๋ฆฝ๋๋ค.
๊ฐ์ฌํฉ๋๋ค ๐โโ๏ธ
import java.util.Collection; | ||
|
||
public interface RoleHierarchy { | ||
Collection<GrantedAuthority> getReachableRoles(Collection<GrantedAuthority> authorities); |
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.
๊ทธ๋ฐ๋ฐ Spring Security ์ฝ๋ ์ ๋ฐ์์๋ Authority๋ฅผ ์ฃผ๋ก ์ฌ์ฉํ๋๋ฐ,
RoleHierarchy์์ ํน๋ณํ Role์ด๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๊ฐ ๊ถ๊ธํ๋ค์.
์ด๋ ๊ฒ Role์ด๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ์ญํ ๋ก ๋น๊ตํ๋ค๊ณ ๋ช ์์ ์ผ๋ก ๋ณด์ฌ์ฃผ๊ธฐ ์ํด์ ์ผ๊น์??
ํน์ ์ด๋ ์ฝ๋์์ RoleHierarchy.getReachableRoles
๋ก ๋์ด์์๊น์? ์ค์ ์คํ๋ง ์ํ๋ฆฌํฐ ์ฝ๋์์๋ ๋ง์ํด์ฃผ์ ๋๋ก authority๋ผ๋ ํํ์ ์ฌ์ฉํ๊ณ ์์ด์.
Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(
Collection<? extends GrantedAuthority> authorities);
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.
์ ๊ฐ ์๋ชป ์ง๋ฌธ์ ๋๋ ธ๋ค์. ์ฃ์กํฉ๋๋ค.
getReachableRoles๋ ๋ฏธ์
์ฝ๋์ ๋ถ๋ถ์ด์๋ค์. ๐
๊ทธ๋๋ Role ์ด๋ฆ์ ์ํ๋ฆฌํฐ์ RoleHierarchy์ ๊ตฌํ์ฒด ์ฝ๋์๋ ์ข
์ข
์ฌ์ฉ๋๋ ๊ฒ ๊ฐ์์
์๋ฅผ ๋ค์ด์ getReachableGrantedAuthorities ์ ๊ตฌํ ๋ฉ์๋ ์ค
Set<GrantedAuthority> lowerRoles = this.rolesReachableInOneOrMoreStepsMap.get(authority.getAuthority());
if (lowerRoles == null) {
continue; // No hierarchy for the role
}
for (GrantedAuthority role : lowerRoles) {
if (processedNames.add(role.getAuthority())) {
reachableRoles.add(role);
}
}
์ ๋ถ๋ถ๋ค ๋ณด๋ฉด Authority ์ Role์ ๊ฐ์ด ์ฌ์ฉํ๋ ๋ฏํด์ RolePrefix์ ๊ด๋ จ์๋๊ฑด๊ฐ? ํ์ต๋๋ค ใ ใ
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.
๋ค spring security์์๋ ์ธ๊ฐ์ฒ๋ฆฌ ๊ถํ(Authority)๊ฐ ์์ง๋ง, ๊ทธ ๊ถํ์ ์ญํ ๋ณ๋ก ๊ณ์ธต์ผ๋ก ๋ถ๋ฆฌํ๋ คํ๊ณ ๊ทธ๋ ๊ฒ ๋์จ ๊ฒ์ด RoleHierarchy
๋ผ๊ณ ๋ณด์๋ฉด ๋ ๊ฒ ๊ฐ์์.
๋ ์ ๋ณด๊ฐ ๋์ผํ ์๋ ์๋๋ฐ ์ฐ์์ ์์ฒด๊ฐ ๊ถํ, ๊ถํ๋ณ ์ญํ ๋ก ํ๋ฒ ๋ ์ชผ๊ฐ์ง๋ค๊ณ ๋ณด์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
public RoleHierarchy roleHierarchy() { | ||
return RoleHierarchyImpl.builder() | ||
.role("ADMIN").addImplies("MEMBER") | ||
.build(); |
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.
์ ์ถ๊ฐํด์ฃผ์ จ๋ค์ ๐
public class NullRoleHierarchy implements RoleHierarchy { | ||
@Override | ||
public Collection<GrantedAuthority> getReachableRoles(Collection<GrantedAuthority> authorities) { | ||
return Collections.emptyList(); | ||
} |
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.
RoleHierarchy
์ ์๋ฌธ๋ช
๊ทธ๋๋ก ์ด ์ธํฐํ์ด์ค์ ์ญํ ์ "์ญํ ๊ณ์ธต"์ ๋ง๋ค์ด์ฃผ๋ ๊ฒ์ด์์. ๊ทธ๋์ ๊ตฌํ์ฒด๋ค๋ ์ญํ ๊ณ์ธต์ ๋ง๋ค์ด์ฃผ๋ ๊ฒ์ผ๋ก ๊ตฌ์ฑ์ด ๋์ด์ผํ๋๋ฐ์.
NullRoleHierarchy
์ด๋ผ๋ ๊ฒ์ null์ด๋ผ๋ ๋ง์ด ํํ๋์ด์๊ธฐ๋ํ์ง๋ง ์ง์ญํ๋ฉด "์ญํ ๊ณ์ธต์ด ์๋ค"์
๋๋ค. ๊ณ์ธต์ด ์๋ค๋ ๊ฒ์ด์ง authority๊ฐ ์๋ค๋ ๋ป์ ์๋๊ธฐ ๋๋ฌธ์ empty๋ฅผ ๋ฐํํ๊ธฐ๋ณด๋ค๋ ์ธ์
๋ ํ๋ผ๋ฉํฐ๋ฅผ ๊ทธ๋๋ก ๋ฐํํด์ฃผ๋ ๊ฒ์ด ๊ทธ ๋ชฉ์ ์ด๋ผ๊ณ ๋ณผ ์ ์์ด์.
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.
์ํ ์ ๋ NULL์ ์ ์ฐ์ง ๋ผ๋ ์๋ฌธ์ด ์์๋๋ฐ , ๋น ๊ถํ์ ์ฃผ๋ ๊ฒ์ด ์๋๋ผ ๋ง ๊ทธ๋๋ก RoleHierarchy ๊ฐ ์๋ค๋ผ๋ ์๋ฏธ๊ตฐ์!
Map<String, Set<GrantedAuthority>> roleHierarchy; | ||
|
||
private static final List<GrantedAuthority> EMPTY_AUTHORITIES = Collections.emptyList(); |
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.
Map<String, Set<GrantedAuthority>> roleHierarchy; | |
private static final List<GrantedAuthority> EMPTY_AUTHORITIES = Collections.emptyList(); | |
private static final List<GrantedAuthority> EMPTY_AUTHORITIES = Collections.emptyList(); | |
private final Map<String, Set<GrantedAuthority>> roleHierarchy; |
์์๋ ์๋ฐ ์ปจ๋ฒค์
์ ๊ฐ์ฅ ์์ ์์ด์ผํ๊ณ , roleHierarchy
๋ ์ ๊ทผ์ ์ด๊ฐ ํ์ํด๋ณด์ด๋ค์ :)
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.
์์ ํ๊ฒ ์ต๋๋ค!
|
||
import java.util.*; | ||
|
||
public class RoleHierarchyImpl implements RoleHierarchy { |
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.
RoleHierarchyImpl
์ ๋ํ ํ
์คํธ๋ ์ถ๊ฐํด๋ณด๋ฉด ์ด๋จ๊น์? ๊ธฐ๋ฅ์ด ๋ณต์กํ ๊ฐ์ฒด์ด๋ ์ด๋ฅผ ๋ฌธ์ํํ๋ค๋ ๋๋์ผ๋ก ํ
์คํธ๋ฅผ ์ง๋ณด์
๋ ์ข์ ๊ฒฝํ์ด ๋ ๊ฒ ๊ฐ์์ :)
- ์ญํ ๊ณ์ธต์ Authority ๋ก ๊ฐ์ ธ์ฌ ์ ์๋ค - ์๋ก์ด ์ญํ ๊ณ์ธต์ ์ถ๊ฐํ ์ ์๋ค. - ์ญํ ์ ์ด๋ฆ์ ๋น์ด์์์ ์๋ค. - ํฌํจ๋ ์ญํ ๋ค๋ ๋น์ด์์ ์ ์๋ค.
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.
์๋ ํ์ธ์ ์ธ์ค๋ ๐
ํผ๋๋ฐฑ ์ ๋ฐ์ํด์ฃผ์
จ๋ค์. ๋ช๊ฐ์ง ์๊ณ ๋์ด๊ฐ๋ฉด ์ข์ ๋ด์ฉ ์ฝ๋ฉํธ ๋จ๊ฒจ๋์์ต๋๋ค.
Authorization ๋ฏธ์
์ ํ์ํ ํ์ต์ ๋ชจ๋ ์ ์งํํด์ฃผ์ ๊ฒ ๊ฐ์ ๋จธ์งํ๊ฒ ์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค ๐โโ๏ธ
@BeforeEach | ||
void setUp() { |
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.
junit5์์๋ ์ด๊ธฐํ ๋จ์๊ฐ ๋ฉ์๋ ๋จ์์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก setup์ผ๋ก ์ด๊ธฐํํด์ฃผ์ ์์ผ์ ๋ ๋ฉ๋๋ค.
https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-instance-lifecycle
@DisplayName("์๋ก์ด ์ญํ ๊ณ์ธต์ ์ถ๊ฐํ ์ ์๋ค.") | ||
void addRoleHierarchyTest() { | ||
// given | ||
String target = "ISRAEL"; | ||
String nothing = "NOTHING"; | ||
String everything = "EVERYTHING"; | ||
RoleHierarchyImpl roleHierarchy = builder.role(target).addImplies(nothing, everything) | ||
.build(); | ||
|
||
// when | ||
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(target); | ||
Collection<GrantedAuthority> reachableRoles = roleHierarchy.getReachableRoles(List.of(authority)); | ||
|
||
// then | ||
var expect = List.of( | ||
authority, | ||
new SimpleGrantedAuthority(nothing), | ||
new SimpleGrantedAuthority(everything) | ||
); |
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.
- ์ถ๊ฐํ๋ค๊ธฐ๋ณด๋ค๋ ๊ณ์ธต์ ๊ฐ์ ธ์จ๋ค์ ๋ ๊ฐ๊น์ด ํ ์คํธ๋ก ๋ณด์ด๋ค์.
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(target);
๋ ๊ทธ๋์ ๋ฐ์ง๊ณ ๋ณด๋ฉด ์ฃผ์ด์ง ๋ฐ์ดํฐ์ธ given์ ๋ ๊ฐ๊น์ต๋๋ค. when์๋ ํ ์คํธ๋ฅผ ์ฆ๋ช ํ๊ณ ์ํ๋ ๋์์ ์คํ ๊ทธ์์ฒด๋ง์ ๋ฃ์ด์ฃผ์๋ฉด ์ข์ ๊ฒ ๊ฐ์์.- expected ๋ํ given์ ๋ค์ด๊ฐ๋ ๊ฒ์ด ๋ง๊ฒ ์ฃ . 74๋ฒ๋ผ์ธ์ ๊ฐ์ ๊ทธ๋๋ก ๋ฃ๋ ๊ฒฝ์ฐ๋ ์๊ด์ด ์์ง๋ง ๊ธฐ๋๊ฐ ๋ํ ์ฃผ์ด์ง ๋ฐ์ดํฐ๋ผ๊ณ ๋ณด๋ ํธ์ ๋๋ค.
String target = "ISRAEL"; | ||
String nothing = "NOTHING"; | ||
String everything = "EVERYTHING"; | ||
RoleHierarchyImpl roleHierarchy = builder.role(target).addImplies(nothing, everything) |
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.
๊ทธ๋์ ์ถ๊ฐํจ(addImplies
)๋ฅผ ํ
์คํธํ๊ณ ์ถ๋ค๋ฉด ์ ๋ง ๊ฐ์ด ์ถ๊ฐ๋์๋์ง ๊ทธ ์์ฒด๋ง์ ํ
์คํธํ๋ ๊ฒ์ด ๋์ ์๋ ์์ด์. private final Map<String, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap;
์ ์ํ๋ ๊ฐ์ด ์๋์ง ํ์ธํ๋ ๊ฒ์ผ๋ก์.
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.
์ ์ฒด ๋์์ด ์๋ rolesReachableInOneOrMoreStepsMap ์์ฒด์ ๊ฐ์ด ์ ์ฅ๋์ด์๋์ง ํ์ธํ๋๊ฒ ์ถ๊ฐ๋์๋๊ฐ ์ ๋ํ ํ ์คํธ๋ก ๋ ์ขํ์ง๊ฒ ๋ค์!
List<GrantedAuthority> expect = switch (roleName) { | ||
case "ADMIN" -> List.of( | ||
new SimpleGrantedAuthority("ADMIN"), | ||
new SimpleGrantedAuthority("MEMBER") | ||
); | ||
case "MEMBER", "UNKNOWN" -> List.of( | ||
new SimpleGrantedAuthority(roleName) | ||
); | ||
default -> throw new IllegalStateException("Unexpected roleName: " + roleName); | ||
}; |
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.
@CsvSource
๋ฅผ ํ์ฉํ๋ฉด ๊ธฐ๋๊ฐ์ ๋ํ ๋ถ๊ธฐ์ฒ๋ฆฌ๋ฅผ ํ
์คํธ์์ ํ์ง ์์๋ ๋ ๊ฒ ๊ฐ์์.
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.
ํ ์คํธ๋ก ์ด๋ค ๊ธฐ๋ฅ์ด ์๋์ง ์ ๋ณด์ด๋ค์ ๐
์๋ ํ์ธ์.
์ ํ - RoleHierarchy ๋ฏธ์ ๋ฆฌ๋ทฐ ์์ฒญํฉ๋๋ค.
์ด๋ฒ ๋ฏธ์ ์ ์ํ๋ฆฌํฐ์์ ๋ช ์์ ์ผ๋ก ๊ฐ๋ฐ๋์ด์๋ ๋ถ๋ถ์ด ๋ง์ ๋น ๋ฅด๊ฒ ๊ฐ๋ฐํ์์ต๋๋ค!
๊ทธ๋ฐ๋ฐ Spring Security ์ฝ๋ ์ ๋ฐ์์๋ Authority๋ฅผ ์ฃผ๋ก ์ฌ์ฉํ๋๋ฐ,
RoleHierarchy์์ ํน๋ณํ Role์ด๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๊ฐ ๊ถ๊ธํ๋ค์.
์๋ฅผ ๋ค์ด:
UserDetails.getAuthorities()
Authentication.getAuthorities()
์์๋ Authority๋ฅผ ์ฌ์ฉํ์ง๋ง
RoleHierarchy.getReachableRoles()
์์๋ Role์ ์ฌ์ฉํ๋ค์.
์ด๋ ๊ฒ Role์ด๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ์ญํ ๋ก ๋น๊ตํ๋ค๊ณ ๋ช ์์ ์ผ๋ก ๋ณด์ฌ์ฃผ๊ธฐ ์ํด์ ์ผ๊น์??
๋ฆฌ๋ทฐ ์ ๋ถํ ๋๋ฆฝ๋๋ค.