在我的React项目中,用户登录,然后重定向到页面'/registergig'
。这是一个受保护的页面,只有登录的用户才可以访问。
在“注册演出”页面上,要求用户输入发布到Firebase数据库的文本数据。但是,当我尝试提交数据时,返回403错误:
index.js:1 Error: Request failed with status code 403
我刚开始实施auth,这有点令人困惑,因此如何使'/registergig'
成为受保护的页面,允许用户提交信息?
这是Login
组件:
import React from 'react'
import Header from './Header'
import Button from '@material-ui/core/Button'
import axios from 'axios'
import {Link} from 'react-router-dom'
class Login extends React.Component {
constructor() {
super();
this.state = {
email: "",
password: "",
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
handleSubmit(e) {
console.log("submit reached");
e.preventDefault();
const loginData = {
email: this.state.email,
password: this.state.password,
};
axios("http://localhost:5000/gig-fort/us-central1/api/login", {
method: "POST",
headers: {
"content-type": "application/json",
},
data: loginData,
})
.then((res) => {
console.log(res.data);
this.props.history.push("/gigregister");
})
.catch((err) => {
console.error(err);
});
}
render() {
return (
<>
<div>
<Header />
</div>
<Link to="/Homepage" style={{ textDecoration: "none" }}>
<h1 className="login-header">Gigs this week</h1>
</Link>
<div className="login-main">
<div className="login">
<h2>Venue login</h2>
<form onSubmit={this.handleSubmit}>
<input
type="text"
name="email"
placeholder="email"
onChange={this.handleChange}
/>
<br></br>
<input
type="password"
name="password"
placeholder="password"
onChange={this.handleChange}
/>
<div className="button">
<Button type="submit">Submit</Button>
</div>
</form>
</div>
<Link to="/venueregister" style={{ textDecoration: "none" }}>
<h2 style={{ color: "#b49650" }}>Register a venue</h2>
</Link>
</div>
</>
);
}
}
export default Login;
这里是GigRegister
组件,它接收用户信息:
import React from "react";
import Header from "./Header";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
import axios from "axios";
class GigRegister extends React.Component {
constructor() {
super();
this.state = {
name: "",
venue: "",
time: "",
date: "",
genre: "",
tickets: "",
price: "",
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
handleSubmit(e) {
console.log("submit function reached");
e.preventDefault();
const gigData = {
name: this.state.name,
venue: this.state.venue,
time: this.state.time,
date: this.state.date,
genre: this.state.genre,
tickets: this.state.tickets,
price: this.state.price,
};
axios("http://localhost:5000/gig-fort/us-central1/api/createGigListing", {
method: "POST",
headers: {
"content-type": "application/json",
},
data: gigData,
})
.then((res) => {
console.log(res.data);
})
.catch((err) => {
console.error(err);
});
}
setDate() {}
render() {
return (
<div className="gig-register">
<Header />
<h1 className="header-gigReg">Register a gig</h1>
<form onSubmit={this.handleSubmit}>
<TextField
placeholder="Event name"
defaultValue="Event name"
id="name"
name="name"
onChange={this.handleChange}
/>
<TextField
placeholder="Venue"
defaultValue="Venue"
id="venue"
name="venue"
onChange={this.handleChange}
/>
<TextField
placeholder="Time"
defaultValue="Time"
type="time"
label="Enter start time"
id="time"
name="time"
InputLabelProps={{
shrink: true,
}}
inputProps={{
step: 300, // 5 min
}}
onChange={this.handleChange}
/>
<TextField
id="date"
label="Select date"
type="date"
defaultValue="2017-05-24"
InputLabelProps={{
shrink: true,
}}
onChange={(e) => {
this.setState({ date: e.target.value });
}}
/>
<TextField
placeholder="Genre"
defaultValue="Genre"
id="genre"
name="genre"
onChange={this.handleChange}
/>
<TextField
placeholder="Tickets"
defaultValue="Tickets"
id="tickets"
name="tickets"
onChange={this.handleChange}
/>
<TextField
placeholder="Price"
defaultValue="Price"
id="price"
name="price"
onChange={this.handleChange}
/>
<Button type="submit">Submit</Button>
</form>
</div>
);
}
}
export default GigRegister
...这是express / firebase函数:
const FBAuth = (req, res, next) => {
let idToken;
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer ')){
idToken = req.headers.authorization.split('Bearer ')[1]
} else {
console.error('No token found')
return res.status(403).json({error: 'Unauthorized'})
}
admin.auth().verifyIdToken(idToken)
.then(decodedToken => {
req.user = decodedToken;
return db.collection('users')
.where('userId', '==',req.user.uid)
.limit(1)
.get()
})
.then(data =>{
req.user.venueName = data.docs[0].data().venueName;
return next();
})
.catch(err => {
console.error('Error while verifying token', err)
return res.status(403).json(err)
})
}
app.post('/createGigListing', FBAuth, (req,res) => {
const newGig = {
venueName: req.user.venueName,
name: req.body.name,
time: req.body.time,
price: req.body.price,
genre: req.body.genre,
tickets: req.body.tickets,
date: req.body.date
}
db
.collection('gig-listing')
.add(newGig)
.then(doc => {
res.json({message: `document ${doc.id} created successfully`})
})
.catch(err =>{
res.status(500).json({error: 'something went wrong'})
console.error(err)
})
})
答案 0 :(得分:1)
您的Cloud Functions代码期望其中包含Authorization
令牌的Bearer
标头,但是您的客户端代码未在此调用中传递该标头:
axios("http://localhost:5000/gig-fort/us-central1/api/createGigListing", {
method: "POST",
headers: {
"content-type": "application/json",
},
data: gigData,
})
因此,您必须在此处添加标头,并传递ID令牌:
firebase.auth().currentUser.getIdToken().then(function(token) {
axios("http://localhost:5000/gig-fort/us-central1/api/createGigListing", {
method: "POST",
headers: {
"content-type": "application/json",
"Authorization": "Bearer "+token,
},
data: gigData,
})
});
我大致基于functions-samples
回购中的this code。