Skip to content

Commit 7a4adfd

Browse files
parkjun5MZC01-PARKJUN5
andauthored
πŸ™Œ 2단계 - 인가(Authorization) 리뷰 μš”μ²­ λ“œλ¦½λ‹ˆλ‹€. (#10)
* feat: add /members/me API - more test for new API * ref: refactoring CheckAuthenticationFilter to AuthorizationFilter - ν•˜λ‚˜μ˜ ν•„ν„°μ—μ„œ μ—¬λŸ¬ 인가 λ‘œμ§μ„ μ²˜λ¦¬ν•˜λ„λ‘ λ³€κ²½ * feat: add AuthorizationManager for authorize - 인증된 μ‚¬μš©μž 체크λ₯Ό μœ„ν•œ AuthorityAuthorizationManager - κΆŒν•œ 체크λ₯Ό μœ„ν•œ SecuredAuthorizationManager μΆ”κ°€ * feat: add request matcher for find AuthorizationManager - MvcRequestMatcher for matching by HttpMethod And URI - AnyRequestMatcher for matching any request * feat: add AuthorizationManagers for delegate Authorities - 인가λ₯Ό μ²˜λ¦¬ν•˜λŠ” λ§€λ‹ˆμ Έλ“€ 생성 - AuthenticatedAuthorizationManager λ‹¨μˆœ 인증 확인 - AuthorityAuthorizationManager λ©”μ„œλ“œμ—μ„œ μ–΄λ…Έν…Œμ΄μ…˜μ„ 가져와 κΆŒν•œ 확인 - PermitAllAuthorizationManager λͺ¨λ“  μš”μ²­ ν—ˆμš© - DenyAllAuthorizationManager λͺ¨λ“  ν—ˆμš© κ±°λΆ€ * ref: change test and Add SecureAnnotation to Get /members API - μœ μ € κΆŒν•œ μ œμ–΄λ₯Ό Interceptorμ—κ²Œ μœ„μž„ν•˜κΈ° μœ„ν•œ Secured μ–΄λ…Έν…Œμ΄μ…˜ μΆ”κ°€ * feat: Filter And Interceptor delegate authorization control to AuthorizationManager - 인터셉터와 ν•„ν„°λŠ” 더이상 직접 인가λ₯Ό ν•΄μ£Όμ§€ μ•Šκ³ , AuthorizationManager λ₯Ό μ‚¬μš©ν•œλ‹€. * feat: add RequestMatcherDelegatingAuthorizationManager and config changed - RequestMatcherDelegatingAuthorizationManager μ—μ„œ μš”μ²­μ— λ§žλŠ” 인가λ₯Ό μ‹œλ„ν•œλ‹€. * docs: μš”κ΅¬ 사항 정리 * polishing * ref: Filter μ—μ„œ μ‚¬μš©ν•˜λŠ” 인가와 Interceptor μ—μ„œ ν™•μΈν•˜λŠ” 인가 뢄리 - ν•„ν„°λŠ” ν•œκ³³μ—μ„œ μ—¬λŸ¬ 인가λ₯Ό μ²˜λ¦¬ν•˜μ§€λ§Œ, MethodInterceptor or Aspect μ—μ„œλŠ” ν•˜λ‚˜μ˜ 인가λ₯Ό 처리 κ·Έλž˜μ„œ ꡳ이 ν•©μ³μ„œ μ²˜λ¦¬ν•  ν•„μš”κ°€ μ—†λŠ”λ“―ν•¨. λ§Œμ•½ ν•„μš”ν•˜λ‹€λ©΄ RequestMatcher ν˜•μ‹μœΌλ‘œ Annotation 을 νŒŒλΌλ―Έν„°λ‘œ 받도둝 처리? - RequestMatcherDelegatingAuthorizationManager λŠ” HttpServletRequest λ₯Ό μ‚¬μš©ν•˜λŠ” λ§€λ‹ˆμ €λ§Œ 등둝(Filter μ‚¬μš©ν•˜λŠ” μ• λ“€) * polishing * ref: - AuthorityAuthorizationManager ν•„ν„°μ—μ„œ μ •ν•΄μ§„ κ°’κ³Ό Authentication.getAuthorities() 비ꡐ - SecuredMethodInterceptor μΈν„°μ…‰ν„°μ—μ„œ Annotation κ°’κ³Ό Authentication.getAuthorities() 비ꡐ * polishing * polishing * ref: Change AuthorityAuthorizationManager to Generic - Stringκ³Ό Collection String을 μ§€μ›ν•˜λ„λ‘ λ³€κ²½ * ref: use verify not check method - AuthorizationDecision 의 λ„μ˜ μœ„ν—˜μ„±κ³Ό μ‚¬μš©λ„ μ•ˆν•˜λŠ” κ²°κ³Όλ₯Ό λ¦¬ν„΄ν•˜λ©΄μ„œ 결과에 λŒ€ν•œ μ˜ˆμ™Έ μ²˜λ¦¬λ„ 일괄성을 κ°€μ§€μ§€ λͺ»ν•˜κΈ°μ— verify λ₯Ό 톡해 κ²€μ¦κΉŒμ§€ μœ„μž„ * ref: AuthorizationDecision 을 static 객체λ₯Ό μ‚¬μš©ν•˜λ„λ‘ λ³€κ²½ * ref: mvc match logic not Stream change to ForEach * ref: SecuredAuthorizationManager μ—μ„œ AuthorityAuthorizationManager μ—κ²Œ 인가 μž‘μ—…μ„ μœ„μž„ν•˜λ„λ‘ λ³€κ²½ - SecuredAuthorizationManager μ—μ„œλŠ” Annotation 값을 ν†΅ν•œ 동적 인가 - RequestMatcherDelegatingAuthorizationManager μ—μ„œλŠ” 인가 μž‘μ—…μ„ ν•˜μ§€ μ•ŠμŒ * test: 인증 μ‹€νŒ¨μ—μ„œλŠ” AccessDeniedException 인가 μ‹€νŒ¨μ—λŠ” ForbiddenException λ‚˜λ„λ‘ λ³€κ²½ --------- Co-authored-by: MZC01-PARKJUN5 <[email protected]>
1 parent 7120f74 commit 7a4adfd

25 files changed

+559
-57
lines changed

β€ŽREADME.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,39 @@
11
# spring-security-authorization
2+
3+
## μ‹€μŠ΅
4+
5+
1. [x] GET /members/me μ—”λ“œν¬μΈνŠΈ κ΅¬ν˜„ 및 ν…ŒμŠ€νŠΈ μž‘μ„±
6+
2. [x] κΆŒν•œ 검증 λ‘œμ§μ„ AuthorizationFilter둜 λ¦¬νŒ©ν„°λ§
7+
8+
## πŸš€ 1단계 - AuthorizationManagerλ₯Ό ν™œμš©
9+
10+
μš”κ΅¬μ‚¬ν•­
11+
12+
- [x] AuthorizationManager λ₯Ό ν™œμš©ν•˜μ—¬ 인가 κ³Όμ • 좔상화
13+
- [x] 인가λ₯Ό μ²˜λ¦¬ν•΄μ€„ AuthorizationManager 생성
14+
- [x] RequestMatcherDelegatingAuthorizationManager λ₯Ό ν†΅ν•œ AuthorizationManager ν•œλ²ˆμ— 관리?
15+
- [x] 인가 과정을 μΆ”μƒν™”ν•œ AuthorizationManager λ₯Ό μž‘μ„±ν•œλ‹€. 이 λ•Œ ν•„μš”ν•œ AuthorizationDecision도 ν•¨κ»˜ μž‘μ„±ν•œλ‹€. (μ‹€μ œ AuthorizationManagerμ—λŠ”
16+
verify도 μžˆλŠ”λ° 이 뢀뢄에 λŒ€ν•œ κ΅¬ν˜„μ€ 선택)
17+
- [x] SecuredMethodInterceptor와 Authorization Filterμ—μ„œ μž‘μ„±λœ 인가 λ‘œμ§μ„ AuthorizationManager둜 λ¦¬νŒ©ν„°λ§ ν•œλ‹€.
18+
19+
## πŸš€ 2단계 - μš”μ²­λ³„ κΆŒν•œ 검증 정보 뢄리
20+
21+
μš”κ΅¬μ‚¬ν•­
22+
23+
- [x] μš”μ²­λ³„ κΆŒν•œ 검증 정보λ₯Ό λ³„λ„μ˜ 객체둜 λΆ„λ¦¬ν•˜μ—¬ 관리
24+
- [x] RequestMatcherRegistry와 RequestMatcherλ₯Ό μž‘μ„±ν•˜κ³ , RequestMatcher의 κ΅¬ν˜„μ²΄λ₯Ό μž‘μ„±ν•œλ‹€.
25+
- [x] AnyRequestMatcher: λͺ¨λ“  경우 trueλ₯Ό λ¦¬ν„΄ν•œλ‹€.
26+
- [x] MvcRequestMatcher: method와 pattern(uri)κ°€ 같은지 λΉ„κ΅ν•˜μ—¬ λ¦¬ν„΄ν•œλ‹€.
27+
- [x] RequestMatcherEntry의 T entryλŠ” μ•„λž˜μ— ν•΄λ‹Ήλ˜λŠ” 각 μš”μ²­λ³„ 인가 λ‘œμ§μ„ λ‹΄λ‹Ήν•˜λŠ” AuthorizationManagerκ°€ λœλ‹€.
28+
- [x] /login은 λͺ¨λ“  μš”μ²­μ„ 받을 수 μžˆλ„λ‘ PermitAllAuthorizationManager둜 처리
29+
- [x] /members/meλŠ” 인증된 μ‚¬μš©μžλ§Œμ—κ²Œλ§Œ κΆŒν•œμ„ λΆ€μ—¬ν•˜κΈ° μœ„ν•΄ AuthenticatedAuthorizationManager둜 처리
30+
- [x] /membersλŠ” "ADMIN" μ‚¬μš©μžλ§Œμ—κ²Œλ§Œ κΆŒν•œμ„ λΆ€μ—¬ν•˜κΈ° μœ„ν•΄ HasAuthorityAuthorizationManager둜 처리
31+
- [x] κ·Έ μ™Έ λͺ¨λ“  μš”μ²­μ€ κΆŒν•œμ„ μ œν•œν•˜κΈ° μœ„ν•΄ DenyAllAuthorizationManager둜 처리
32+
33+
μ•„λž˜ 객체와 μ‹œνλ¦¬ν‹° μ½”λ“œ 확인
34+
// SpEL
35+
// Role Authority
36+
// Role Hierarchy
37+
// AuthoritiesAuthorizationManager
38+
// SecureMethodSecurityConfiguration
39+
// SecuredAuthorizationManager

β€Žsrc/main/java/nextstep/app/SecurityConfig.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
package nextstep.app;
22

3+
import jakarta.servlet.http.HttpServletRequest;
34
import nextstep.app.domain.Member;
45
import nextstep.app.domain.MemberRepository;
56
import nextstep.security.authentication.AuthenticationException;
67
import nextstep.security.authentication.BasicAuthenticationFilter;
78
import nextstep.security.authentication.UsernamePasswordAuthenticationFilter;
8-
import nextstep.security.authorization.CheckAuthenticationFilter;
9-
import nextstep.security.authorization.SecuredAspect;
9+
import nextstep.security.authorization.AuthorizationFilter;
1010
import nextstep.security.authorization.SecuredMethodInterceptor;
11+
import nextstep.security.authorization.manager.*;
1112
import nextstep.security.config.DefaultSecurityFilterChain;
1213
import nextstep.security.config.DelegatingFilterProxy;
1314
import nextstep.security.config.FilterChainProxy;
1415
import nextstep.security.config.SecurityFilterChain;
1516
import nextstep.security.context.SecurityContextHolderFilter;
17+
import nextstep.security.matcher.AnyRequestMatcher;
18+
import nextstep.security.matcher.MvcRequestMatcher;
19+
import nextstep.security.matcher.RequestMatcherEntry;
1620
import nextstep.security.userdetails.UserDetails;
1721
import nextstep.security.userdetails.UserDetailsService;
1822
import org.springframework.context.annotation.Bean;
1923
import org.springframework.context.annotation.Configuration;
2024
import org.springframework.context.annotation.EnableAspectJAutoProxy;
25+
import org.springframework.http.HttpMethod;
2126

27+
import java.util.ArrayList;
2228
import java.util.List;
2329
import java.util.Set;
2430

@@ -44,21 +50,32 @@ public FilterChainProxy filterChainProxy(List<SecurityFilterChain> securityFilte
4450

4551
@Bean
4652
public SecuredMethodInterceptor securedMethodInterceptor() {
47-
return new SecuredMethodInterceptor();
53+
AuthorityAuthorizationManager<Set<String>> authorityAuthorizationManager = new AuthorityAuthorizationManager<>();
54+
return new SecuredMethodInterceptor(new SecuredAuthorizationManager(authorityAuthorizationManager));
4855
}
4956
// @Bean
5057
// public SecuredAspect securedAspect() {
5158
// return new SecuredAspect();
5259
// }
5360

61+
@Bean
62+
public RequestMatcherDelegatingAuthorizationManager requestMatcherDelegatingAuthorizationManager() {
63+
List<RequestMatcherEntry<AuthorizationManager<HttpServletRequest>>> mappings = new ArrayList<>();
64+
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/members/me"), new AuthenticatedAuthorizationManager()));
65+
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/members"), new AuthorityAuthorizationManager<>()));
66+
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/search", "/login"), new PermitAllAuthorizationManager()));
67+
mappings.add(new RequestMatcherEntry<>(new AnyRequestMatcher(), new DenyAllAuthorizationManager()));
68+
return new RequestMatcherDelegatingAuthorizationManager(mappings);
69+
}
70+
5471
@Bean
5572
public SecurityFilterChain securityFilterChain() {
5673
return new DefaultSecurityFilterChain(
5774
List.of(
5875
new SecurityContextHolderFilter(),
5976
new UsernamePasswordAuthenticationFilter(userDetailsService()),
6077
new BasicAuthenticationFilter(userDetailsService()),
61-
new CheckAuthenticationFilter()
78+
new AuthorizationFilter(requestMatcherDelegatingAuthorizationManager())
6279
)
6380
);
6481
}

β€Žsrc/main/java/nextstep/app/ui/MemberController.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
import nextstep.app.domain.Member;
44
import nextstep.app.domain.MemberRepository;
5+
import nextstep.security.authentication.AuthenticationException;
6+
import nextstep.security.authentication.UsernamePasswordAuthenticationToken;
57
import nextstep.security.authorization.Secured;
8+
import nextstep.security.context.SecurityContextHolder;
69
import org.springframework.http.ResponseEntity;
710
import org.springframework.web.bind.annotation.GetMapping;
811
import org.springframework.web.bind.annotation.RestController;
912

1013
import java.util.List;
14+
import java.util.NoSuchElementException;
1115

1216
@RestController
1317
public class MemberController {
@@ -18,16 +22,28 @@ public MemberController(MemberRepository memberRepository) {
1822
this.memberRepository = memberRepository;
1923
}
2024

25+
@Secured("ADMIN")
2126
@GetMapping("/members")
2227
public ResponseEntity<List<Member>> list() {
2328
List<Member> members = memberRepository.findAll();
2429
return ResponseEntity.ok(members);
2530
}
2631

27-
@Secured("ADMIN")
32+
@Secured({"ADMIN", "MEMBER"})
2833
@GetMapping("/search")
2934
public ResponseEntity<List<Member>> search() {
3035
List<Member> members = memberRepository.findAll();
3136
return ResponseEntity.ok(members);
3237
}
38+
39+
@GetMapping("/members/me")
40+
public ResponseEntity<Member> getMyInfo() {
41+
if (SecurityContextHolder.getContext().getAuthentication() instanceof UsernamePasswordAuthenticationToken token
42+
&& token.getPrincipal() instanceof String email) {
43+
Member member = memberRepository.findByEmail(email).orElseThrow(NoSuchElementException::new);
44+
return ResponseEntity.ok(member);
45+
}
46+
47+
throw new AuthenticationException();
48+
}
3349
}

β€Žsrc/main/java/nextstep/security/authentication/BasicAuthenticationFilter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import jakarta.servlet.FilterChain;
44
import jakarta.servlet.http.HttpServletRequest;
55
import jakarta.servlet.http.HttpServletResponse;
6+
import nextstep.security.authorization.ForbiddenException;
67
import nextstep.security.context.SecurityContext;
78
import nextstep.security.context.SecurityContextHolder;
89
import nextstep.security.userdetails.UserDetailsService;
@@ -40,6 +41,8 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
4041
SecurityContextHolder.setContext(context);
4142

4243
filterChain.doFilter(request, response);
44+
} catch (ForbiddenException e) {
45+
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
4346
} catch (Exception e) {
4447
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
4548
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package nextstep.security.authorization;
2+
3+
import org.springframework.http.HttpStatus;
4+
import org.springframework.web.bind.annotation.ResponseStatus;
5+
6+
@ResponseStatus(HttpStatus.FORBIDDEN)
7+
public class AccessDeniedException extends RuntimeException {
8+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package nextstep.security.authorization;
2+
3+
public class AuthorizationDecision {
4+
5+
private static final AuthorizationDecision GRANTED = new AuthorizationDecision(true);
6+
private static final AuthorizationDecision DENIED = new AuthorizationDecision(false);
7+
8+
private final boolean isGranted;
9+
10+
public static AuthorizationDecision granted() {
11+
return GRANTED;
12+
}
13+
14+
public static AuthorizationDecision denied() {
15+
return DENIED;
16+
}
17+
18+
protected AuthorizationDecision(final boolean isGranted) {
19+
this.isGranted = isGranted;
20+
}
21+
22+
public boolean isDenied() {
23+
return !isGranted;
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,28 @@
11
package nextstep.security.authorization;
22

3-
import nextstep.security.authentication.Authentication;
4-
import nextstep.security.context.SecurityContextHolder;
5-
import org.springframework.web.filter.OncePerRequestFilter;
6-
73
import jakarta.servlet.FilterChain;
84
import jakarta.servlet.ServletException;
95
import jakarta.servlet.http.HttpServletRequest;
106
import jakarta.servlet.http.HttpServletResponse;
7+
import nextstep.security.authentication.Authentication;
8+
import nextstep.security.authorization.manager.RequestMatcherDelegatingAuthorizationManager;
9+
import nextstep.security.context.SecurityContextHolder;
10+
import org.springframework.web.filter.OncePerRequestFilter;
11+
1112
import java.io.IOException;
12-
import java.util.Set;
1313

14-
public class CheckAuthenticationFilter extends OncePerRequestFilter {
15-
private static final String DEFAULT_REQUEST_URI = "/members";
14+
public class AuthorizationFilter extends OncePerRequestFilter {
15+
16+
private final RequestMatcherDelegatingAuthorizationManager authorizationManager;
17+
18+
public AuthorizationFilter(RequestMatcherDelegatingAuthorizationManager authorizationManager) {
19+
this.authorizationManager = authorizationManager;
20+
}
1621

1722
@Override
1823
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
19-
if (!DEFAULT_REQUEST_URI.equals(request.getRequestURI())) {
20-
filterChain.doFilter(request, response);
21-
return;
22-
}
23-
2424
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
25-
if (authentication == null || !authentication.isAuthenticated()) {
26-
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
27-
return;
28-
}
29-
30-
Set<String> authorities = authentication.getAuthorities();
31-
if (!authorities.contains("ADMIN")) {
32-
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
33-
return;
34-
}
35-
25+
authorizationManager.verifyInFilter(request, authentication);
3626
filterChain.doFilter(request, response);
3727
}
3828
}

β€Žsrc/main/java/nextstep/security/authorization/Secured.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
@Target(ElementType.METHOD)
99
@Retention(RetentionPolicy.RUNTIME)
1010
public @interface Secured {
11-
String value();
11+
String[] value() default {"ADMIN"};
1212
}

β€Žsrc/main/java/nextstep/security/authorization/SecuredAspect.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,24 @@
99
import org.aspectj.lang.reflect.MethodSignature;
1010

1111
import java.lang.reflect.Method;
12+
import java.util.Arrays;
1213

1314
@Aspect
1415
public class SecuredAspect {
1516

1617
@Before("@annotation(nextstep.security.authorization.Secured)")
1718
public void checkSecured(JoinPoint joinPoint) throws NoSuchMethodException {
1819
Method method = getMethodFromJoinPoint(joinPoint);
19-
String secured = method.getAnnotation(Secured.class).value();
20+
String[] secured = method.getAnnotation(Secured.class).value();
2021
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
2122
if (authentication == null) {
2223
throw new AuthenticationException();
2324
}
24-
if (!authentication.getAuthorities().contains(secured)) {
25+
26+
boolean hasNoRole = authentication.getAuthorities()
27+
.stream()
28+
.noneMatch(auth -> Arrays.asList(secured).contains(auth));
29+
if (hasNoRole) {
2530
throw new ForbiddenException();
2631
}
2732
}

β€Žsrc/main/java/nextstep/security/authorization/SecuredMethodInterceptor.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package nextstep.security.authorization;
22

33
import nextstep.security.authentication.Authentication;
4-
import nextstep.security.authentication.AuthenticationException;
4+
import nextstep.security.authorization.manager.AuthorizationManager;
55
import nextstep.security.context.SecurityContextHolder;
66
import org.aopalliance.aop.Advice;
77
import org.aopalliance.intercept.MethodInterceptor;
@@ -11,29 +11,21 @@
1111
import org.springframework.aop.framework.AopInfrastructureBean;
1212
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
1313

14-
import java.lang.reflect.Method;
1514

1615
public class SecuredMethodInterceptor implements MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
1716

1817
private final Pointcut pointcut;
18+
private final AuthorizationManager<MethodInvocation> authorizationManager;
1919

20-
public SecuredMethodInterceptor() {
20+
public SecuredMethodInterceptor(AuthorizationManager<MethodInvocation> authorizationManager) {
21+
this.authorizationManager = authorizationManager;
2122
this.pointcut = new AnnotationMatchingPointcut(null, Secured.class);
2223
}
2324

2425
@Override
2526
public Object invoke(MethodInvocation invocation) throws Throwable {
26-
Method method = invocation.getMethod();
27-
if (method.isAnnotationPresent(Secured.class)) {
28-
Secured secured = method.getAnnotation(Secured.class);
29-
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
30-
if (authentication == null) {
31-
throw new AuthenticationException();
32-
}
33-
if (!authentication.getAuthorities().contains(secured.value())) {
34-
throw new ForbiddenException();
35-
}
36-
}
27+
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
28+
authorizationManager.verify(authentication, invocation);
3729
return invocation.proceed();
3830
}
3931

0 commit comments

Comments
Β (0)