内网的项目虽然看起来非常安全外网无法访问, 但是也有可能遭遇黑客的攻击, 同时内网项目遭遇攻击后对于公司的损失是非常大的。 所以权限校验、身份验证、鉴权登录就非常重要了。
基于我阅读的大量文章 , 虽然目前内网上很多网站都有文章教程, 但是都不够完整。 只是零星的提及了ioa鉴权登录接入的极个别部分 ,有很多地方还是容易踩坑。 所以我这里做了整理。 通过自己负责的项目,完整的将ioa鉴权登录的前后端代码做一个讲解。 有误之处还请指出。
整体的业务流程是根据太湖中提供的demo案例的流程图 , 但是我这里也做了细分。
添加描述
具体的appkey、以及code内容这里就不做显示了。但凡仔细阅读过太湖文档的大家应该都是清楚的。 这里我们来说一下请求重定向这一块的问题
因为按照业务流程图, 我们可以知道大致的流程走向,但是具体怎么做 我们就需要再来梳理一下了。根据逻辑图(简易画法~), 前端在判断是否存在Token之后, 进行请求跳转, 如果不存在cookie则直接跳转至登录页面。
这里需要注意前端跳转的跨域问题
我这里为了避免跨域问题, 直接使用了`window.location.href` , 其实也可以使用axios或者jsonp等请求, 只要能够跳转即可。
在前置守卫中做拦截,然后再进行转发到ioa登录界面
// 添加全局前置导航守卫
router.beforeEach((to, from, next) => {
// 判断token是否存在
const token = Cookie.get('token')
if (token) {
next()
}else{
if(to.name === ''|| to.name === 'login'){
next()
}else{
const callbackUrl = `https://.woa.com`; // 回调URL
const redirect = encodeURIComponent(to.fullPath);
const loginUrl = `https://passport.woa.com/modules/passport/signin.ashx?oauth=true&url=${callbackUrl}&appkey=${app_key}&redirect=${redirect}`;
window.location.href = loginUrl;
}
}
})
复制
下面就是前端这块最关键的步骤, 如何获取回调的url, 然后发送请求?
因为回调的url中 ,他只能回调到'/' 路径,对于我们拼接的资源路径。 他是不会跳转的。 所以我们需要再router/index.js中对于路径path = '/'的我们需要跳转到正确的login的view。 这个view他不做展示,仅仅是接收跳转过来code, 然后再发送请求, 获取到用户信息。 最后再跳转到主页中显示
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const code = urlParams.get('code');
复制
后续就是发送具体的请求了, 这里不做赘述
前面可以知道, 从前端获取到了code, 但是前端并不擅长解析code, 我们需要后端来完成解密票据接口。
v1.POST("/getuserinfo", func(c *gin.Context) {
code := c.Query("code")
// fmt.Println("code == =", code)
if code == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "code is required"})
return
}
// var res ResponseBody
sendGetRequest(code)
// 处理code数据的代码
c.JSON(http.StatusOK, res)
})
复制
前端将请求发送到后端, 并且携带了请求的code。 后端拿到code之后, 首先需要对用户身份进行验证。
注意: 这里验证身份和发送请求获取用户信息都需要太湖中的应用token 和 paasid
然后再拼接header发送获取AccessToken请求。同时需要输入请求参数code, 这里的具体参数我们可以看这里。 当然这个API也是需要申请的。
// setHeaders set headers
func setHeaders(token, paasid string) map[string]string {
timestamp := strconv.Itoa(int(time.Now().Unix()))
nonce := timestamp
signData := fmt.Sprintf("%s%s%s%s", timestamp, token, nonce, timestamp)
signature := strings.ToUpper(fmt.Sprintf("%x", sha256.Sum256([]byte(signData))))
return map[string]string{
"x-rio-timestamp": timestamp,
"x-rio-nonce": nonce,
"x-rio-signature": signature,
"x-rio-paasid": paasid,
}
}
复制
// 发送请求
func sendGetRequest(code string) ResponseBody {
url := "https://XXXX.com/AccessToken?code=" + code
// var TofApiResp models.APIResponse
header := setHeaders(token, paasid)
TofApiResp, err := Get(url, GetTimeOut(), header)
if err != nil {
res.Code = -1
res.Msg = err.Error()
fmt.Println("Error sending GET request:", err)
return res
}
var apiResponse models.APIResponse
respon, err := processTofReqApiResp(TofApiResp, err)
if err != nil {
res.Code = -1
res.Msg = err.Error()
fmt.Println("Error sending GET request:", err)
return res
}
apiResponse = convertTofApiResp(*respon)
go PutDB(apiResponse.Data)
res.Data = apiResponse //需要补充
res.Msg = "获取用户信息成功!"
res.Code = 0
return res
}
复制
这里具体细节的请求内容都在太湖文档中有, 当然具体的如何进行解密也可以参考文档中的demo。
按照上述的鉴权流程, 基本上可以完成简易的前后端分离项目的对接智能网关进行鉴权登录。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。