使用 Spring Security OAuth2 和 Vaadin flow 21 登录

Login with Spring Security OAuth2 and Vaadin flow 21

我正在尝试为我的 Discord Bot 创建一个 Web 界面,并且很想添加一个“使用 Discord 登录”的方法。我创建了两个视图来测试 OAuth 登录系统。

第一个视图是索引/主页视图,其中包含“使用 discord 登录”按钮。

@PageTitle("Home")
@Route(value = "")
@AnonymousAllowed
public class HomeView extends VerticalLayout {
    private final OAuth2AuthorizedClientService clientService;

    public HomeView(OAuth2AuthorizedClientService clientService) {
        this.clientService = clientService;
        setSpacing(false);
        setPadding(false);
        add(navbar());
        add(body());
    }

    private Component navbar() {
        HorizontalLayout root = new HorizontalLayout();
        root.setWidthFull();
        root.setAlignItems(Alignment.CENTER);
        Span name = new Span("Unity");
        name.getStyle().set("padding-left", "1rem");
        root.add(name);

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (!(authentication instanceof OAuth2AuthenticationToken)) {
            Button loginButton = new Button();
            Image discordLogo = new Image("images/discord.svg", "discord_logo.png");
            discordLogo.getStyle().set("padding-top", "0.5rem");
            loginButton.setIcon(discordLogo);
            loginButton.setText("Login with Discord");
            loginButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
            loginButton.getStyle().set("padding-right", "1rem");
            loginButton.addClassName("toolbar");
            Anchor anchor = new Anchor("/oauth2/authorization/discord", loginButton);
            anchor.getElement().setAttribute("router-ignore", true);
            root.add(anchor);
        } else {
            Notification.show("Logged In");
            OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
            OAuth2AuthorizedClient client = this.clientService.loadAuthorizedClient(token.getAuthorizedClientRegistrationId(), token.getName());
            String accessToken = client.getAccessToken().getTokenValue();
            Notification.show("Logged in with token: " + accessToken);
        }

        root.setFlexGrow(1, name);
        root.addClassNames("contrast-5pct");

        return root;
    }


    private Component body() {
        VerticalLayout root = new VerticalLayout();
        Image img = new Image("images/empty-plant.png", "placeholder plant");
        img.setWidth("200px");
        root.add(img);

        root.add(new H2("This place intentionally left empty"));
        root.add(new Paragraph("It’s a place where you can grow your own UI "));

        root.setSizeFull();
        root.setJustifyContentMode(JustifyContentMode.CENTER);
        root.setDefaultHorizontalComponentAlignment(Alignment.CENTER);
        root.getStyle().set("text-align", "center");

        return root;
    }
}

另一个视图是用户认证成功后的视图

@Route("test")
public class TestView extends VerticalLayout {
    public TestView() {
        add("It Works! :D");
    }
}

我当前的 spring oauth 配置如下所示:

spring:
  security:
    oauth2:
      client:
        registration:
          discord:
            client-id: <id>
            client-secret: <secret>
            clientAuthenticationMethod: post
            authorizationGrantType: authorization_code
            scope:
              - identify
              - guilds
            redirectUri: "{baseUrl}/login/oauth2/callback/{registrationId}"
            clientName: Discord-Client
        provider:
          discord:
            authorizationUri: https://discordapp.com/api/oauth2/authorize
            tokenUri: https://discordapp.com/api/oauth2/token
            userInfoUri: https://discordapp.com/api/users/@me
            usernameAttribute: username

我的 Spring 安全配置如下所示:

@Configuration
public class SecurityConfig extends VaadinWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/oauth2/authorization/discord", "/login/oauth2/callback/**").permitAll();
        http.oauth2Login(oauth -> {
            oauth.defaultSuccessUrl("/test");
            })
            .logout(logout -> {
                logout.logoutSuccessUrl("/");
            });

        super.configure(http);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
        web.ignoring().antMatchers(
            "/images/**"
        );
    }

    @Bean
    public RestOperations restOperations() {
        return new RestTemplate();
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}

我已经尝试实施此 post 中的解决方案: 但它一直将我重定向到主页视图并且用户未通过身份验证。

我是否遗漏了对用户进行身份验证的内容!?

提前感谢您的帮助!

我的问题已经解决了。我的 redirectUri 错了^^"

将它从 {baseUrl}/login/oauth2/callback/{registrationId} 更改为 {baseUrl}/login/oauth2/code/{registrationId} 后,它没有任何问题