Защита REST API с помощью аннотаций @PreAuthorize (hasRole ('ROLE_NEW')), в которых роль извлекается из KeyCloak JWT - PullRequest
0 голосов
/ 30 августа 2018

Моя цель - защитить конечную точку API REST в приложении Spring Boot с помощью аннотации @PreAuthorize(hasRole('ROLE_NEW')). Роль должна быть извлечена из JWT, предоставленного KeyCloak.

RestController ниже. Проект аналогичен SpringBoot REST Service, защищенному с помощью Keycloak Authorization Services .

@RestController
public class ApplicationController {

    @PreAuthorize(hasRole('ROLE_NEW'))
    @RequestMapping(value = "/api/resourceannotated", method = RequestMethod.GET)

    public String handleResourceAnnotated() {
        return createResponse();
    }

    @RequestMapping(value = "/api/resourcea", method = RequestMethod.GET)
    public String handleResourceA() {
        return createResponse();
    }

    @RequestMapping(value = "/api/resourceb", method = RequestMethod.GET)
    public String handleResourceB() {
        return createResponse();
    }

    @RequestMapping(value = "/api/premium", method = RequestMethod.GET)
    public String handlePremiumResource() {
        return createResponse();
    }

    @RequestMapping(value = "/api/admin", method = RequestMethod.GET)
    public String handleAdminResource() {
        return createResponse();
    }

    private String createResponse() {
        return "Access Granted";
    }

Пользователь test с ролью NEW был добавлен в KeyCloak , и я ожидал, что запросы будут отправлены с JWTs в / api / аннотированная ресурсом конечная точка должна быть авторизована только для пользователей с ролью NEW , которые будут извлечены из JWT .

Мотивация - сохранение запроса в KeyCloak , который обеспечивает контроль доступа к / api / resourcea, / api / resourceb, / api / premium, / api / admin конечные точки с использованием политик.

Как это сделать правильно? Попытка Использование JWT с аннотацией Spring Security @PreAuthorize для безопасности, специфичной для метода и ИСПОЛЬЗОВАНИЕ KEYCLOAK С ПРИЛОЖЕНИЕМ SPRING BOOT 2 безуспешно. Я получаю ошибку ниже:

{ «метка времени»: «2018-08-30T14: 37: 39,409 + 0000», «статус»: 401, «ошибка»: «Несанкционированный», «сообщение»: «Несанкционированный», "путь": "/ api / resourceannotated"}

При запуске в режиме отладки выводятся 2 сообщения:

2018-08-30 17: 55: 47.586 DEBUG 31006 --- [nio-8180-exec-3] o.s.b.w.s.f.OrderedRequestContextFilter: привязать контекст запроса к поток: org.apache.catalina.connector.RequestFacade@62b92856 2018-08-30 17: 55: 47.592 DEBUG 31006 --- [nio-8180-exec-3] o.s.b.w.s.f.OrderedRequestContextFilter: очищенная привязка к потоку контекст запроса: org.apache.catalina.connector.RequestFacade@62b92856

Включено ведение журнала отладки для org.springframework.security

и получение следующих ошибок:

DEBUG 30677 --- [           main] s.s.c.a.w.c.WebSecurityConfigurerAdapter : Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).
 DEBUG 30677 --- [           main] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'authenticated', for org.springframework.security.web.util.matcher.AnyRequestMatcher@1
 DEBUG 30677 --- [           main] o.s.s.w.a.i.FilterSecurityInterceptor    : Validated configuration attributes
 DEBUG 30677 --- [           main] o.s.s.w.a.i.FilterSecurityInterceptor    : Validated configuration attributes
  INFO 30677 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@31c2affc, org.springframework.security.web.context.SecurityContextPersistenceFilter@f72203, org.springframework.security.web.header.HeaderWriterFilter@2d2acd89, org.springframework.security.web.csrf.CsrfFilter@6e1d4137, org.springframework.security.web.authentication.logout.LogoutFilter@149f5761, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@1237e0be, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@2ab2710, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@6441c486, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@540dbda9, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@27b000f7, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1dc2de84, org.springframework.security.web.session.SessionManagementFilter@1e6dad8, org.springframework.security.web.access.ExceptionTranslationFilter@2d5f7182, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@58a4a74d]
  INFO 30677 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
  INFO 30677 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8180 (http) with context path ''
  INFO 30677 --- [           main] o.k.quickstart.springboot.MyApplication  : Started MyApplication in 14.439 seconds (JVM running for 17.843)
  INFO 30677 --- [] o.k.a.authorization.PolicyEnforcer       : Paths provided in configuration.
  INFO 30677 --- [] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
  INFO 30677 --- [] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
  INFO 30677 --- [] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 73 ms
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
 DEBUG 30677 --- [] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
 DEBUG 30677 --- [] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 4 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 5 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
 DEBUG 30677 --- [] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /api/resourceannotated' doesn't match 'POST /logout
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 6 of 14 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
 DEBUG 30677 --- [] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /api/resourceannotated' doesn't match 'POST /login
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 7 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 8 of 14 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 9 of 14 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 10 of 14 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 11 of 14 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
 DEBUG 30677 --- [] o.s.s.w.a.AnonymousAuthenticationFilter  : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@c551e2ad: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@1de6: RemoteIpAddress: 10.88.0.23; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 12 of 14 in additional filter chain; firing Filter: 'SessionManagementFilter'
 DEBUG 30677 --- [] o.s.s.w.session.SessionManagementFilter  : Requested session ID A64F605948A7B529457A226B238A5EEC is invalid.
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 13 of 14 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
 DEBUG 30677 --- [] o.s.security.web.FilterChainProxy        : /api/resourceannotated at position 14 of 14 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
 DEBUG 30677 --- [] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /api/resourceannotated; Attributes: [authenticated]
 DEBUG 30677 --- [] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@c551e2ad: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@1de6: RemoteIpAddress: 10.88.0.23; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
 DEBUG 30677 --- [] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@14cd10fa, returned: -1
 DEBUG 30677 --- [] o.s.s.w.a.ExceptionTranslationFilter     : Access is denied (user is anonymous); redirecting to authentication entry point

org.springframework.security.access.AccessDeniedException: Access is denied
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...