Vaadin应用程序(Java:19,Vaadin:24.0.5,Spring Boot:3.0.6) 在SSO登录后未获取角色

我有一个VAADIN项目,想确保我的观点.MainView.java应允许访问具有@RolesAllowed({"ROLE_ADMIN", "ADMIN"})的用户.通过我的SSO服务登录后,用户将通过身份验证并获得必要的角色:

Retrieved SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Principal=Name: [USERTEST], Granted Authorities: [[OAUTH2_USER, SCOPE_company]], User Attributes: [{userCode=USERTEST, userTeam=T_X, userEmail=user@company.at, userKtksnr=0, roles=[ADMIN, ROLE_ADMIN], principal={authorities=[], details={remoteAddress=127.0.0.1, sessionId=null, tokenValue=H7G7LR-Ghiq5BmPFqcuGrAt5ZxI, tokenType=Bearer, decodedDetails=null}, authenticated=true, userAuthentication={authorities=[], details={remoteAddress=0:0:0:0:0:0:0:1, sessionId=BFE069B0209E3DADDEFBCFC1BACB23A9}, authenticated=true, principal={userCode=USERTEST, userTeam=T_X, userEmail=user@company.at, userKtksnr=0, roles=[ADMIN, ROLE_ADMIN]}, credentials=null, name=User{userCode='USERTEST', userTeam='T_X', userEmail='user@company.at', userKtksnr=0, roles=[ADMIN, ROLE_ADMIN]}}, clientOnly=false, credentials=, oauth2Request={clientId=company, scope=[company], requestParameters={code=PSVUul, grant_type=authorization_code, scope=company, response_type=code, state=R6czQI2wlFbfNwfqoulg6ckrthGnTS4JJjS7nkdAlg0=, redirect_uri=http://localhost:7060/company/login/oauth2/code/company, client_id=company}, resourceIds=[], authorities=[], approved=true, refresh=false, redirectUri=http://localhost:7060/company/login/oauth2/code/company, responseTypes=[code], extensions={}, refreshTokenRequest=null, grantType=authorization_code}, principal={userCode=USERTEST, userTeam=T_X, userEmail=user@company.at, userKtksnr=0, roles=[ADMIN, ROLE_ADMIN]}, name=User{userCode='USERTEST', userTeam='T_X', userEmail='user@company.at', userKtksnr=0, roles=[ADMIN, ROLE_ADMIN]}}, applicationRoles=ADMIN,ROLE_ADMIN}], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=5278B052E19AD339C2CCF1A20E5ACA8D], Granted Authorities=[OAUTH2_USER, SCOPE_company]]]

带有注释@PermitAll的TestView.java按照预期的方式工作(无需身份验证,重定向到SSO,带有身份验证的视图可见).

但带有注释@RolesAllowed({"ROLE_ADMIN", "ADMIN"})的MainView.java访问始终被拒绝:

Client Application:

MainView.java

import com.vaadin.flow.component.html.*;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import jakarta.annotation.security.RolesAllowed;

@PageTitle("MainView")
@Route(value = "", layout = MainLayout.class)
@RolesAllowed({"ROLE_ADMIN", "ADMIN"})
public class MainView extends VerticalLayout {
    public MainView() {
        H3 title = new H3("Application");
        add(title);
    }
}

UiSecurityConfig.java

import com.vaadin.flow.spring.security.VaadinWebSecurity;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@EnableWebSecurity
@Configuration
public class UiSecurityConfig extends VaadinWebSecurity {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests().requestMatchers(new AntPathRequestMatcher("/public/**"))
                .permitAll()
                .and()
                .oauth2Login() ;
        super.configure(http);
    }
}

Application.yml

server:
  port: 7060
  servlet:
    context-path: /application
spring:
  security:
    oauth2:
      client:
        registration:
          company:
            client-id: application
            client-secret:
            scope: MAM
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:7060/application/login/oauth2/code/company
        provider:
          company:
            authorization-uri: http://localhost:9090/sso-service/auth/oauth/authorize
            token-uri: http://localhost:9090/sso-service/auth/oauth/token
            user-info-uri: http://localhost:9090/sso-service/auth/user/me
            user-name-attribute: userCode
resourceserver:
  api:
    project:
      url: http://localhost:9090/sso-service/auth/user/me
logging:
  level:
    org:
      springframework:
        security: DEBUG

Spring-oauth2-SSO-Application:

下面是自定义的"UserController",其中调用"/User/Me",用户将获得所有信息:

@RestController
public class UserController {

private QueryUserDataTemplate queryTemplate;

@Autowired
public UserController(QueryUserDataTemplate queryTemplate) {
    this.queryTemplate = queryTemplate;
}

@GetMapping("/user/me")
public User user(Principal principal) {
    User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

    String clientId = ((OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication()).getOAuth2Request().getClientId();
    List<String> roleList = queryTemplate.queryForApplicationRoles(user.getSybCode(), clientId);
    if (roleList != null) {
        user.setRoles((Collection) roleList);
    }
    return new UserResult(principal, user.getSybCode(), user.getSybTeam(), user.getSybEmail(), user.getSybKtksnr(), user.getRoles(), user.getAuthorities());
}


public static class UserResult extends User {

    private final Principal principal;

    private UserResult(Principal principal, String username, String sybTeam, String sybEmail, Long sybktksnr,
                       Collection applicationRoles, List<GrantedAuthority> authorities) {
        super(username, sybTeam, sybEmail, sybktksnr, applicationRoles, authorities);
        this.principal = principal;
    }

    public Principal getPrincipal() {
        return principal;
    }
}

如果您需要任何其他信息,请让我知道!

编辑: 调试信息:

Request received for POST '/?v-r=uidl&v-uiId=0':

org.apache.catalina.connector.RequestFacade@24c0d321

servletPath:/
pathInfo:null
headers: 
host: localhost:7060
connection: keep-alive
content-length: 529
sec-ch-ua: "Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"
sec-ch-ua-platform: "Windows"
sec-ch-ua-mobile: ?0
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36
content-type: application/json; charset=UTF-8
accept: */*
origin: http://localhost:7060
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty
referer: http://localhost:7060/mam/
accept-encoding: gzip, deflate, br
accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
cookie: JSESSIONID=F95188E5E420170BFF950B0C8D6BB8C6


Security filter chain: [
  DisableEncodeUrlFilter
  WebAsyncManagerIntegrationFilter
  SecurityContextHolderFilter
  HeaderWriterFilter
  CsrfFilter
  LogoutFilter
  OAuth2AuthorizationRequestRedirectFilter
  OAuth2LoginAuthenticationFilter
  DefaultLoginPageGeneratingFilter
  DefaultLogoutPageGeneratingFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  ExceptionTranslationFilter
  AuthorizationFilter
]

推荐答案

您已经定义了一个OAuth2客户端安全配置(OAuth2登录和基于会话的安全性),但是没有为authorities mapping=>提供任何内容;用户信息中的"Roles"声明的值不会转换为Spring授权.

向当局曝光GrantedAuthoritiesMapper个豆子转换角色可能就足够了.

我建议你阅读我在上面链接的文档和my tutorials.

Java相关问答推荐

使用log 4j2格式的Hibernate 显示SQL日志(log)

try 使用Java 9或更高版本对特殊对象图进行解析时出现NullPointerException

Java自定义ThreadPool—暂停任务提交并取消当前排队任务

如何在返回bigint []值的子查询中使用any?

我无法将附件发送到NetBeans之外

对运行在GraalVM-21上的JavaFX应用程序使用分代ZGC会警告不支持JVMCI,为什么?

如何使用Maven和Spring Boot将构建时初始化、跟踪类初始化正确传递到本机编译

如何创建一个2d自上而下的移动系统,其中移动,同时持有两个关键是可能的处理?

使用GridBagLayout正确渲染

如何在Java中从XML中获取特定的 node ,然后将其删除?

在Java中如何从Executors.newFixedThreadPool(MAX_THREAD_COUNT())迁移到虚拟线程

与Spring Boot相关的实体未正确保存

有效的公式或值列表必须少于或等于255个字符

允许同时执行两个方法,但不能同时执行这两个方法

错误:未找到扩展元素在JBossEAP 7.2中安装FUSE时出错

FETCH类型设置为LAZY,但它仍会发送第二个请求

如何在字节数组中反转UTF-8编码?

在Eclipse中可以使用外部字体吗?

Java CDI:@Singleton@Startup@Inject无法实现接口

OpenJDK20:JEP434:Foreign Function&;内存API(第二次预览)