通过Beego实现远程鉴权服务器
通过Beego实现远程鉴权服务器
背景:
在一次处理远程鉴权不生效的问题时,远程鉴权一直返回403.怀疑是请求的URL没有携带参数导致。于是在自己的域名上部署同样配置才发现问题原因。
处理完成这个问题后,也突发奇想自己也写一个接口来实现远程鉴权的功能。同时来检验下beego的学习成果。
鉴权的概念
URL鉴权功能主要用于保护用户站点的资源不被非法站点下载盗用。通过防盗链方法添加Referer黑名单和白名单的方式可以解决一部分盗链问题,由于Referer内容可以伪造,所以Referer防盗链方式无法彻底保护站点资源。
鉴权的分类大致分为两类
- CDN厂商鉴权
- 远程鉴权
由于CDN厂商写好的鉴权都是写好的功能,优点是在节点完成,不用担心可靠性,不需要自身实现额外的功能。缺点是可拓展性比较差,不能很好的定制需求。
远程鉴权是用户向CDN节点发出请求时,CDN节点会向远程鉴权服务器发送请求,在得到指定的信息后(比如200状态码通过,403状态码拒绝),CDN节点给用户返回数据或拒绝请求。
通过Beego来实现远程鉴权
实现的逻辑大概分为以下几步:
- 创建Beego API
- 定义好处理规则和路由
- 部署在nginx上
创建Beego API
使用bee命令创建beego api项目
bee api jianquan
定义好处理规则和路由
路由部分使用注解路由来实现
#在router.go中的init函数中添加
beego.Include(&controllers.AuthController{})
逻辑处理部分
以阿里云CDN A监权为例:
请求url格式为:http://domain/1.txt?auth_key=1612093559-0-0-aeceba32c9dd967aa68a9a5f6af9194c
向鉴权服务器发送的url为:http://auth/auth?auth_key=1612093559-0-0-aeceba32c9dd967aa68a9a5f6af9194c&uri=/1.txt
#在controllers目录下创建 authentication.go
package controllers
import (
"crypto/md5"
"encoding/hex"
"io"
"strconv"
"strings"
"time"
"github.com/astaxie/beego"
)
type AuthController struct {
beego.Controller
}
//定义鉴权的key值
const Key = "jiangfeng1234"
// @router /auth [get]
func (this *AuthController) Auth() {
authKey := this.GetString("auth_key")
uri := this.GetString("uri")
if authKey == "" || uri == "" {
this.Ctx.ResponseWriter.WriteHeader(403)
}
//定义auth_key的切片 格式示例:["1612087953","0","0","17445e81d5da62e400a30dbde80a5946"]
authSlices := strings.Split(authKey, "-")
//获取鉴权中的时间和 现在的时间
nowTime := time.Now().Unix()
authTime, err := strconv.ParseInt(authSlices[0], 10, 64)
if err != nil || authTime < nowTime {
this.Ctx.ResponseWriter.WriteHeader(403)
}
buildString := uri + "-" + authSlices[0] + "-0-0-" + Key
md5Str := md5sum(buildString)
if string(md5Str) == authSlices[3] {
this.Ctx.WriteString(string(md5Str))
} else {
this.Ctx.ResponseWriter.WriteHeader(403)
}
}
//md5计算
func md5sum(str string) string {
m := md5.New()
io.WriteString(m, str)
return hex.EncodeToString(m.Sum(nil))
}
项目部署
1.go build打包上传服务器
2.nohup 运行项目,项目结构为
.
└── auth
├── conf
│ └── app.conf
├── jianquan
└── nohup.out
3.nginx反向代理
location /auth {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:8080;
}
测试结果:
jiangfeng@jiangfeng-Default-string:~/go/src/jianquan$ curl -voa "www.fengzhigu.world/auth?auth_key=1612093559-0-0-aeceba32c9dd967aa68a9a5f6af9194c&uri=/1.txt"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 106.15.248.82:80...
* TCP_NODELAY set
* Connected to www.fengzhigu.world (106.15.248.82) port 80 (#0)
> GET /auth?auth_key=1612093559-0-0-aeceba32c9dd967aa68a9a5f6af9194c&uri=/1.txt HTTP/1.1
> Host: www.fengzhigu.world
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.16.1
< Date: Sun, 31 Jan 2021 10:46:34 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 32
< Connection: keep-alive
<
{ [32 bytes data]
100 32 100 32 0 0 395 0 --:--:-- --:--:-- --:--:-- 395
* Connection #0 to host www.fengzhigu.world left intact
jiangfeng@jiangfeng-Default-string:~/go/src/jianquan$ curl -voa "www.fengzhigu.world/auth?auth_key=1612093559-0-0-aeceba32c9dd967aa68a9a5f6af9194c&uri=/1.tx"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 106.15.248.82:80...
* TCP_NODELAY set
* Connected to www.fengzhigu.world (106.15.248.82) port 80 (#0)
> GET /auth?auth_key=1612093559-0-0-aeceba32c9dd967aa68a9a5f6af9194c&uri=/1.tx HTTP/1.1
> Host: www.fengzhigu.world
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< Server: nginx/1.16.1
< Date: Sun, 31 Jan 2021 12:03:49 GMT
< Content-Length: 0
< Connection: keep-alive
<
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* Connection #0 to host www.fengzhigu.world left intact