如何用oauth2 spring引导解决cors错误并作出React

yacmzcpb  于 2021-07-23  发布在  Java
关注(0)|答案(0)|浏览(191)

我想开发一个应用程序,用户需要使用暴雪帐户连接他们。
我使用SpringBoot2.4.2作为后端,react 17.0.0作为前端。
这就是我使用Spring Security 和oauth2身份验证的原因。
当我单击login按钮时,我调用endpoint/user/isaccountexist来检查用户是否在应用程序上注册。
但是当我尝试调用端点时,前端在http://localhost:3000(使用npm run start)我有一个错误。
呼叫htpp://localhost:3000之前
我试过把前端放进去http://localhost:2142(由后端公开),但我有相同的错误。
呼叫htpp://localhost:2142之前
之后,我想尝试用浏览器直接调用端点(http://localhost:2142/user/isaccountexist)我看到了这一点。
直接打电话
当我再次点击前端的按钮(http://localhost:3000和http://localhost:2142)有效。
呼叫htpp://localhost:3000之后
呼叫htpp://localhost:2142之后
所以,我不知道在电话打不通之前发生了什么,为什么。
谢谢您。
我链接github存储库:https://github.com/opendoha/myguild/tree/login_page
我链接了一部分代码
用户控制器.java

package fr.opendoha.myguild.server.controller;

import fr.opendoha.myguild.server.dto.UserAccountDTO;
import fr.opendoha.myguild.server.exception.UserBattleTagAlreadyUsedException;
import fr.opendoha.myguild.server.exception.UserBlizzardIdAlreadyUsedException;
import fr.opendoha.myguild.server.exception.UserEmailAlreadyUsedException;
import fr.opendoha.myguild.server.exception.UserNickNameAlreadyUsedException;
import fr.opendoha.myguild.server.parameters.FetchingUserAccountParameter;
import fr.opendoha.myguild.server.parameters.UserRegistrationParameter;
import fr.opendoha.myguild.server.service.UserService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Controller used to manage users
 */
@RestController
@RequestMapping("user")
public class UserController extends MotherController {

    protected final UserService userService;

    /**
     * Constructor
     */
    @Autowired
    public UserController(final UserService userService) {
        super();
        this.userService = userService;
    }

    /**
     * Endpoint used to check if the account exist
     */
    @GetMapping("/isAccountExist")
    public Boolean isAccountExist(final OAuth2AuthenticationToken authentication) {

        final Integer blizzardId = this.getBlizzardId(authentication);

        return this.userService.checkUserAccountAlreadyExist(blizzardId);
    }

}

安全配置.java

package fr.opendoha.myguild.server.security;

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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**-
 * Class configuration used to configure spring security
 */
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    /**
     * Configuration of security
     */
    @Override
    public void configure(final HttpSecurity http) throws Exception {

        http
            .cors()
            .and().csrf().disable()
            .antMatcher("/**").authorizeRequests()
            .antMatchers("/", "index.html", "/favicon.ico", "/*manifest.json", "workbox-*/*.js", "/*.js", "/*.png", "/static/**", "/*.svg", "/*.jpg").permitAll()
            .anyRequest().authenticated()
            .and().logout().logoutSuccessUrl("/")
            .and().oauth2Login();
    }

}

应用程序.yml

application:
  server:
    port: 2142
    url: http://localhost
  db-param:
    host: localhost
    port: 3306
    db-name:********
    user:********
    password:********
  blizzard:
    wow:
      delay-ms: 10
      profile:
        base-uri: https://eu.api.blizzard.com/profile
        namespace: profile-eu
      game-data:
        base-uri: https://eu.api.blizzard.com/data/wow
        namespace: static-eu

logging:
  level:
    fr.opendoha.myguild.server:
      tools:
        HttpHelper: INFO
        handler.GlobalExceptionHandler: INFO
      MyGuildApplication: INFO
      service:
        BlizzardService: INFO
        oauth2:
          BlizzardOAuth2FlowHandler: INFO
      aop.interceptor: 
        GeneralInterceptor: INFO
        ServiceInterceptor: INFO
    org:
      apache: INFO
      springframework:
        web.client.RestTemplate: INFO
        security: INFO
        data: INFO

server:
  port : ${application.server.port}

spring:
  jpa:
    show-sql: false
    database-platform : org.hibernate.dialect.MySQL5InnoDBDialect
    hibernate:
      ddl-auto: create-drop
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
  security:
    oauth2:
      client:
        registration:
          oauth-blizzard:
            client-id:********
            client-secret:********
            client-name:********
            provider: blizzard
            scope: wow.profile
            redirect-uri: "${application.server.url}:${application.server.port}/login/oauth2/code/oauth-blizzard"
            client-authentication-method: basic
            authorization-grant-type: authorization_code 
        provider:
          blizzard:
            issuer-uri: https://eu.battle.net/oauth
            authorization-uri: https://eu.battle.net/oauth/authorize
            token-uri: https://eu.battle.net/oauth/token
            user-info-uri: https://eu.battle.net/oauth/userinfo
            user-name-attribute: battletag

  datasource:
    url: jdbc:mysql://${application.db-param.host}:${application.db-param.port}/${application.db-param.db-name}
    username: ${application.db-param.user}
    password: ${application.db-param.password}
    driverClassName: com.mysql.cj.jdbc.Driver

登录组件(loginpaper.tsx)

import { Box, Button, makeStyles, Paper, Typography } from '@material-ui/core'
import React from 'react'
import Logo from './../../img/BlizzardLogo.svg'
import { UserHttpClient } from '../../api/httpclient/UserHttpClient'

export default function LoginPaper() {
  const classes = useStyles()

  const toto = async () => {

    const userHttpClient = new UserHttpClient()

    userHttpClient.isAccountExist()
    .then((value) => {
      console.log(value)
    })
    .catch((reason) => {
      console.log(reason)
    })

  }

  return (
    <Paper className={classes.paper} variant="outlined">
      <Box
        className={classes.box}
        display="flex"
        flexDirection="column"
        justifyContent="space-around"
        alignItems="center"
      >
        <Typography variant="h1" className={classes.title}>
          My Guild
        </Typography>
        <Button
          variant="contained"
          color="primary"
          className={classes.loginButton}
          onClick={toto}
        >
          <img src={Logo} className={classes.iconButton} />
          <div className={classes.buttonLabel}>Login with BLIZZARD</div>
        </Button>
      </Box>
    </Paper>
  )
}

用户httpclient.ts

import { AddUserParameter } from "./../Entities"
import HttpClient from "./HttpClient"

export class UserHttpClient extends HttpClient {

    constructor(){
        super(false)
    }

    public async isAccountExist(): Promise<boolean> {
        const response = await this.get("/user/isAccountExist")
        return response.data as boolean
    }

}

httpclient.ts文件

import Axios, { AxiosError, AxiosResponse } from 'axios'
import ApiError from './ApiError'

export default class HttpClient {
  public static readonly FOUND_STATUS = 403
  public static readonly UNAUTHORIZED_ERROR_STATUS = 401
  public static readonly FORBIDDEN_ERROR_STATUS = 403
  public static readonly INTERNAL_SERVER_ERROR_STATUS = 501
  public static readonly INTERNAL_SERVER_ERROR_MESSAGE =
    'An internal server error occured'

  private redirectIfUnauthorized: boolean

  constructor(redirectIfUnauthorized: boolean = true) {
    this.redirectIfUnauthorized = redirectIfUnauthorized
  }

  protected async get(
    apiUrl: string,
    queryParams?: { [key: string]: any },
    headers?: { [key: string]: any },
  ) {
    return this.manageErrors(() =>
      Axios.get(apiUrl, {
        params: queryParams,
        headers: this.buildHeader(headers),
      }),
    )
  }

  protected async post(
    apiUrl: string,
    data: any,
    headers?: { [key: string]: any },
  ) {
    return this.manageErrors(() =>
      Axios.post(apiUrl, data, {
        headers: this.buildHeader(headers),
      }),
    )
  }

  private buildHeader(headers?: {
    [key: string]: any
  }): { [key: string]: any } {
    return {
      'Content-Type': 'application/json',
      ...headers,
    }
  }

  private async manageErrors(
    apiCall: () => Promise<AxiosResponse>,
  ): Promise<AxiosResponse> {
    try {
      const response: AxiosResponse = await apiCall()
      return response
    } catch (err) {
      const error: AxiosError = err as AxiosError

      if (error.response) {
        if (
          this.redirectIfUnauthorized === true &&
          error.response.status === HttpClient.UNAUTHORIZED_ERROR_STATUS
        ) {
          window.location.href = '/'
        }
        throw new ApiError(
          error.response.status,
          error.response.statusText,
          error.response.data,
        )
      } else if (error.request) {
        throw new ApiError(
          HttpClient.INTERNAL_SERVER_ERROR_STATUS,
          HttpClient.INTERNAL_SERVER_ERROR_MESSAGE,
          error.request,
        )
      } else {
        throw new ApiError(
          HttpClient.UNAUTHORIZED_ERROR_STATUS,
          error.message,
          null,
        )
      }
    }
  }
}

package.json(部分)

"dependencies": {
    "axios": "^0.21.1",
}

"proxy": "http://localhost:2142"

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题