Node.js 如何向我的web应用程序的用户显示不同的内容?梅恩栈
我正在尝试制作一个投票应用程序,每个用户只能投票一次。为了做到这一点,我保存了已经投票的用户的ip,并将其与使用该应用程序的用户的ip进行比较。因此,如果他的ip与数据库中已经存在的ip匹配,他将得到一个屏幕,显示他不能再次投票。 问题是,如果一个用户投票,其他所有用户都会在屏幕上说他们不能投票 这是后端代码,用于获取用户ip和数据库中的所有ip,并在投票时发布ip:Node.js 如何向我的web应用程序的用户显示不同的内容?梅恩栈,node.js,reactjs,express,mongoose,Node.js,Reactjs,Express,Mongoose,我正在尝试制作一个投票应用程序,每个用户只能投票一次。为了做到这一点,我保存了已经投票的用户的ip,并将其与使用该应用程序的用户的ip进行比较。因此,如果他的ip与数据库中已经存在的ip匹配,他将得到一个屏幕,显示他不能再次投票。 问题是,如果一个用户投票,其他所有用户都会在屏幕上说他们不能投票 这是后端代码,用于获取用户ip和数据库中的所有ip,并在投票时发布ip: const express = require("express"); const router = express.Route
const express = require("express");
const router = express.Router();
const ipify = require("ipify");
const mongoose = require("mongoose");
const internalIp = require("internal-ip");
const ipModel = require("../../models/Ip");
// @route GET api/ip
// @desc obtener todas las ip de la db
// @access public
router.get("/", (req, res) => {
ipModel
.find()
.then(ip => {
res.status(200).json(ip);
})
.catch(err => res.status(404).json(err));
});
// @route POST api/ip
// @desc Guardar la ip en la db
// @access public
router.post("/", (req, res) => {
internalIp
.v4()
.then(miip => {
ipModel
.findOne({ ip: miip })
.then(laip => {
if (laip) {
return res
.status(400)
.json({ ip: "Su voto se ha realizado exitosamente" });
} else {
const newIp = new ipModel({
ip: miip
});
newIp.save().then(ip => res.json(newIp));
}
})
.catch(err => res.status(404).json(err));
})
.catch(err => res.json(err));
});
// @route GET api/ip/miip
// @desc Guardar la ip en la db
// @access public
router.get("/miip", (req, res) => {
internalIp
.v4()
.then(miip => {
res.status(200).json(miip);
})
.catch(err => res.json(err));
});
module.exports = router;
这是管理前端投票逻辑的组件的代码:
import React, { Component } from "react";
import { Redirect } from "react-router-dom";
import { Container, ListGroup, ListGroupItem, Button } from "reactstrap";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import axios from "axios";
class Votos extends Component {
constructor() {
super();
this.state = {
carrozas: [],
ipRegistradas: [],
miIp: null,
goToVotos: true
};
this.votar = this.votar.bind(this);
}
componentDidMount() {
axios
.get("/api/ip")
.then(ips => {
this.setState(prevState => ({
ipRegistradas: [...prevState.ipRegistradas, ...ips.data]
}));
})
.catch(err => console.log(err));
axios
.get("/api/carrozas")
.then(carrozasdb => {
this.setState(prevState => ({
carrozas: [...prevState.carrozas, ...carrozasdb.data]
}));
})
.catch(err => console.log(err));
axios
.get("/api/ip/miip")
.then(miip => {
this.setState({
miIp: miip.data
});
})
.catch(err => console.log(err));
}
shouldRedirect() {
for (var i = 0; i < this.state.ipRegistradas.length; i++) {
if (this.state.ipRegistradas[i].ip === this.state.miIp) {
this.setState({
goToVotos: false
});
}
}
}
votar(nom) {
axios.post("/api/votos", { nombre: nom });
axios.post("/api/ip");
}
render() {
const { carrozas } = this.state;
this.shouldRedirect();
if (this.state.goToVotos === true) {
return (
<Container>
<h3
style={{
display: "flex",
justifyContent: "center",
alignItems: "center"
}}
>
Votá la mejor carroza...
</h3>
<ListGroup>
<TransitionGroup className="carrozas">
{carrozas.map(({ _id, nombre, curso }) => (
<CSSTransition key={_id} timeout={500} classNames="fade">
<ListGroupItem
style={{
display: "flex",
justifyContent: "spaceAround"
}}
>
<Button
className="votar-btn"
color="primary"
size="sm"
onClick={() => {
this.votar(nombre);
this.props.history.push("/votoexitoso");
}}
>
Votar
</Button>
"{nombre}"
<p
style={{
marginLeft: "5rem"
}}
>
{curso}
</p>
</ListGroupItem>
</CSSTransition>
))}
</TransitionGroup>
</ListGroup>
</Container>
);
} else {
return <Redirect to="votoexitoso" />;
}
}
}
export default Votos;
import React,{Component}来自“React”;
从“react router dom”导入{Redirect};
从“reactstrap”导入{Container、ListGroup、ListGroupItem、Button};
从“react transition group”导入{CSTranslation,TransitionGroup};
从“axios”导入axios;
类Votos扩展了组件{
构造函数(){
超级();
此.state={
卡罗萨斯:[],
IPDAS:[],
miIp:null,
戈托沃托斯:是的
};
this.votar=this.votar.bind(this);
}
componentDidMount(){
axios
.get(“/api/ip”)
。然后(ips=>{
this.setState(prevState=>({
ipRegistradas:[…prevState.ipRegistradas,…ips.data]
}));
})
.catch(err=>console.log(err));
axios
.get(“/api/carrozas”)
.然后(carrozasdb=>{
this.setState(prevState=>({
carrozas:[…prevState.carrozas,…carrozasdb.data]
}));
})
.catch(err=>console.log(err));
axios
.get(“/api/ip/miip”)
。然后(miip=>{
这是我的国家({
miIp:miIp.data
});
})
.catch(err=>console.log(err));
}
shouldRedirect(){
for(var i=0;i(
{
这是votar(nombre);
this.props.history.push(“/votoexitoso”);
}}
>
伏塔
“{nombre}”
{curso}
))}
);
}否则{
返回;
}
}
}
导出默认Votos;
内部ip
提供您的服务器ip地址。要获取客户端IP地址,您可以使用request.connection.remoteAddress
或request.headers['x-forwarded-for']
(如果服务器位于代理之后)
router.post(“/”,(req,res)=>{
const ip=req.connection.remoteAddress;
...
使用客户端IP地址而不是服务器IP地址如何解决问题?好的,当用户投票时,您将其IP地址存储在数据库中,并且只有在数据库中找不到其IP地址时才允许投票(对吗?)。如果您使用服务器IP地址,您实际上是在将您的服务器地址与以前存储的服务器地址进行比较,因此每个人都会收到“无法投票”消息。我已经尝试了您的解决方案,并且效果良好。谢谢。但我现在有另一个问题。每次在电话中使用应用程序投票时,数据库中都会保存一个不同的IP地址对于相同的设备,它总是允许通用的,IP地址不是识别用户身份的可靠方法,它们是动态的并且可以随着时间而改变。如果您需要100%确定该用户以前没有投票,请考虑使用另一种方法,例如注册。注册。如果我使用cookies而不是IP地址或注册方法?