我想开发一个应用程序,用户需要使用暴雪帐户连接他们。
我使用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"
暂无答案!
目前还没有任何答案,快来回答吧!