refer: http://ip-api.com/
1.首先需要创建一个保存用户历史的登录的表,然后连接go
2.在用户登录的时候,获取用户的IP IP位置,在后端直接处理数据即可(不需要在前端传递数据)
(1)增加路由:
apiv1.POST("/history_login_logs", v1.AddHistoryLoginLog)
(2)在model里增加(例如:models/history_login_logs.go)
func AddHistoryLoginLog(user_id int, ip_address string, ip_location string, login_at time.Time) bool {
db.Create(&HistoryLoginLogs{
UserId: user_id,
IpAddress: ip_address,
IpLocation: ip_location,
LoginAt: login_at,
})
return true
}
(3) 在登录后的方法中增加(需要引入
import(
"time"
"io/ioutil"
"fmt"
"encoding/json"
)
type Location struct {
Status string `json:"status"`
Country string `json:"country"`
CountryCode string `json:"countryCode"`
Region string `json:"region"`
RegionName string `json:"regionName"`
City string `json:"city"`
Zip string `json:"zip"`
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
Timezone string `json:"timezone"`
Isp string `json:"isp"`
Org string `json:"org"`
As string `json:"as"`
Query string `json:"query"`
}
...
ipAddress := c.ClientIP()
fmt.Println("== ip_address:", ipAddress)
resp, err := http.Get("http://ip-api.com/json/" + ipAddress + "?lang=zh-CN")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error:", err)
return
}
var location Location
err = json.Unmarshal(body, &location)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("=== Location:", location)
City := location.City
currentTime := time.Now()
models.AddHistoryLoginLog(user.ID, ipAddress, City, currentTime)
...
(4)增加action (例如:routers/api/v1/history_login_log.go)(需要引入import "net/http" "time" "fmt")
type AddHistoryLoginLogRequest struct {
UserID int `json:"user_id" binding:"required"`
IPAddress string `json:"ip_address" binding:"required"`
City string `json:"ip_location" binding:"required"`
CurrentTime time.Time `json:"login_at" binding:"required"`
}
func AddHistoryLoginLog(c *gin.Context) {
var request AddHistoryLoginLogRequest
if err := c.ShouldBindJSON(&request); err != nil {
fmt.Println("== err: ", err)
return
}
models.AddHistoryLoginLog(request.UserID, request.IPAddress, request.City, request.CurrentTime)
}
3.在前端写一个展示的列表页面即可。(登录时间写现在的时间即可。)
例如:src/pages/HistoryLoginLog/index.jsx
import React, { Component } from 'react'
import { Table } from 'antd';
import axios from 'axios'
import Config from '@/settings'
import { getToken, removeToken } from '@/utils/auth'
const columns = [
{
title: '登录名',
dataIndex: 'user_id',
key: 'user_id',
render: text => {text},
},
{
title: '登陆时间',
dataIndex: 'login_at',
key: 'login_at',
// 这里是进行时间的处理,转换为北京时间,格式为:2023/08/16 21:40
render: text => {
const dateObj = new Date(text);
const localizedDate = dateObj.toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
});
return {localizedDate};
},
},
{
title: '登陆ip',
dataIndex: 'ip_address',
key: 'ip_address',
},
{
title: '登陆位置',
dataIndex: 'ip_location',
key: 'ip_locatio',
}
];
export default class CalculationPlan extends Component {
state = {
data: [],
loading: true,
}
async fetchData() {
try {
const response = await axios.get(`${Config.BASE_URL}/api/v1/history_login_logs?token=${getToken()}`)
if (response.data.message == "ok") {
const sortedData = response.data.data.sort((a, b) => new Date(b.id) - new Date(a.id));
this.setState({
data: sortedData,
loading: false,
})
}
} catch (error) {
console.error(error)
removeToken()
window.location.href = '/'
}
}
componentDidMount() {
this.fetchData()
}
render() {
const { data, loading } = this.state
return (
)
}
}