《使用 IdentityServer 保护 Web 应用(AntD Pro 前端 + SpringBoot 后端)》中记录了使用 IdentityServer 保护前后端的过程,其中的前端工程是以 UMI Js 为例。今天,再来记录一下使用 IdentityServer 保护 Vue 前端的过程,和 UMI Js 项目使用 umi plugin 的方式不同,本文没有使用 Vue 相关的插件,而是直接使用了 oidc-client js。
另外,我对 Vue 这个框架非常不熟,在 vue-router 这里稍微卡住了一段时间,后来瞎试居然又成功了。针对这个问题,我还去 StackOverflow 上问了,但并没有收到有效的回复:https://stackoverflow.com/questions/74769607/how-to-access-vues-methods-from-navigation-guard
(资料图片仅供参考)
首先,需要在 IdentityServer 服务器端注册该 Vue 前端应用,仍然以代码写死这个客户端为例:
new Client{ClientId = "vue-client",ClientSecrets = { new Secret("vue-client".Sha256()) },ClientName = "vue client",AllowedGrantTypes = GrantTypes.Implicit,AllowAccessTokensViaBrowser = true,RequireClientSecret = false,RequirePkce = true,RedirectUris ={"http://localhost:8080/callback","http://localhost:8080/static/silent-renew.html",},AllowedCorsOrigins = { "http://localhost:8080" },AllowedScopes = { "openid", "profile", "email" },AllowOfflineAccess = true,AccessTokenLifetime = 90,AbsoluteRefreshTokenLifetime = 0,RefreshTokenUsage = TokenUsage.OneTimeOnly,RefreshTokenExpiration = TokenExpiration.Sliding,UpdateAccessTokenClaimsOnRefresh = true,RequireConsent = false,};在 Vue 工程里安装 oidc-client
yarn add oidc-client在 Vue 里配置 IdentityServer 服务器信息
在项目里添加一个 src/security/security.js文件:
import Oidc from "oidc-client"function getIdPUrl() {return "https://id6.azurewebsites.net";}Oidc.Log.logger = console;Oidc.Log.level = Oidc.Log.DEBUG;const mgr = new Oidc.UserManager({authority: getIdPUrl(),client_id: "vue-client",redirect_uri: window.location.origin + "/callback",response_type: "id_token token",scope: "openid profile email",post_logout_redirect_uri: window.location.origin + "/logout",userStore: new Oidc.WebStorageStateStore({store: window.localStorage}),automaticSilentRenew: true,silent_redirect_uri: window.location.origin + "/silent-renew.html",accessTokenExpiringNotificationTime: 10,})export default mgr在 main.js 里注入登录相关的数据和方法数据
不借助任何状态管理包,直接将相关的数据添加到 Vue 的 app 对象上:
import mgr from "@/security/security";const globalData = {isAuthenticated: false,user: "",mgr: mgr}方法
const globalMethods = {async authenticate(returnPath) {console.log("authenticate")const user = await this.$root.getUser();if (user) {this.isAuthenticated = true;this.user = user} else {await this.$root.signIn(returnPath)}},async getUser() {try {return await this.mgr.getUser();} catch (err) {console.error(err);}},signIn(returnPath) {returnPath ? this.mgr.signinRedirect({state: returnPath}) : this.mgr.signinRedirect();}}修改 Vue 的实例化代码
new Vue({router,data: globalData,methods: globalMethods,render: h => h(App),}).$mount("#app")修改 router
在 src/router/index.js中,给需要登录的路由添加 meta 字段:
Vue.use(VueRouter)const router = new VueRouter({{path: "/private",name: "private page",component: resolve => require(["@/pages/private.vue"], resolve),meta: {requiresAuth: true}}});export default router
接着,正如在配置中体现出来的,需要一个回调页面来接收登录后的授权信息,这可以通过添加一个 src/views/CallbackPage.vue文件来实现:
<script>export default {async created() {try {const result = await this.$root.mgr.signinRedirectCallback();const returnUrl = result.state ?? "/";await this.$router.push({path: returnUrl})}catch(e){await this.$router.push({name: "Unauthorized"})}}}</script>Sign-in in progress... 正在登录中……
然后,需要在路由里配置好这个回调页面:
import CallbackPage from "@/views/CallbackPage.vue";Vue.use(VueRouter)const router = new VueRouter({routes: {path: "/private",name: "private page",component: resolve => require(["@/pages/private.vue"], resolve),meta: {requiresAuth: true}},{path: "/callback",name: "callback",component: CallbackPage}});export default router
同时,在这个 router 里添加一个所谓的“全局前置守卫”(https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB),注意就是这里,我碰到了问题,并且在 StackOverflow 上提了这个问题。在需要调用前面定义的认证方法时,不能使用 router.app.authenticate,而要使用 router.apps[1].authenticate,这是我通过 inspect router发现的:
...router.beforeEach(async function (to, from, next) {let app = router.app.$data || {isAuthenticated: false}if(app.isAuthenticated) {next()} else if (to.matched.some(record => record.meta.requiresAuth)) {router.apps[1].authenticate(to.path).then(()=>{next()})}else {next()}})export default router
到了这一步,应用就可以跑起来了,在访问 /private 时,浏览器会跳转到 IdentityServer 服务器的登录页面,在登录完成后再跳转回来。
添加 silent-renew.html注意 security.js,我们启用了 automaticSilentRenew,并且配置了 silent_redirect_uri的路径为 silent-renew.html。它是一个独立的引用了 oidc-client js 的 html 文件,不依赖 Vue,这样方便移植到任何前端项目。
oidc-client.min.js首先,将我们安装好的 oidc-client 包下的 node_modules/oidc-client/dist/oidc-client.min.js文件,复制粘贴到 public/static目录下。
然后,在这个目录下添加 public/static/silent-renew.html文件。
给 API 请求添加认证头Silent Renew Token <script src="oidc-client.min.js"></script><script>console.log("renewing tokens");new Oidc.UserManager({userStore: new Oidc.WebStorageStateStore({ store: window.localStorage })}).signinSilentCallback();</script>
最后,给 API 请求添加上认证头。前提是,后端接口也使用同样的 IdentityServer 来保护(如果是 SpringBoot 项目,可以参考《[使用 IdentityServer 保护 Web 应用(AntD Pro 前端 + SpringBoot 后端) - Jeff Tian的文章 - 知乎](https://zhuanlan.zhihu.com/p/533197284) 》);否则,如果 API 是公开的,就不需要这一步了。
对于使用 axios 的 API 客户端,可以利用其 request interceptors,来统一添加这个认证头,比如:
import router from "../router"import Vue from "vue";const v = new Vue({router})const service = axios.create({// 公共接口--这里注意后面会讲baseURL: process.env.BASE_API,// 超时时间 单位是ms,这里设置了3s的超时时间timeout: 20 * 1000});service.interceptors.request.use(config => {const user = v.$root.user;if(user) {const authToken = user.access_token;if(authToken){config.headers.Authorization = `Bearer ${authToken}`;}}return config;}, Promise.reject)export default service
标签:
-
使用 IdentityServer 保护 Vue 前端:全球热资讯
前情提要《使用IdentityServer保护Web应用(AntDPro前端+SpringBoot后端)》中记录了使用IdentitySer
-
经营贷禁止流入房市 违规“转贷”有资金链断裂风险
12月20日,银保监会发布关于警惕不法贷款中介诱导消费者违规转贷的
-
汽车购置税领跌,前11月财政收入下降3%
12月20日下午,财政部发布数据显示1至11月累计,全国一般公共预算收入185518亿元,扣除留抵退税因素后增长6 1%,按自然口径计算下降3%。 其
-
天舟五号成功释放“澳门学生科普卫星一号”:环球视讯
新京报讯(记者张建林)北京时间2022年12月20日,澳门举行回归祖国23周年纪念活动,在活动现场,澳门特别行政区行政长官贺一诚宣布天舟五号货
-
环球快看:招商中证畜牧养殖ETF净值下跌2.75% 请保持关注
招商中证畜牧养殖ETF净值下跌2 75%请保持关注
-
聚焦高科技领域发展 银亿股份更名山子股份获股东大会通过:焦点热闻
2022年12月19日晚间,银亿股份发布公告称,公司当日召开的2022年第二次临时股东大会审议通过了《关于变更公司名称、证券简称及修订<公司章程>
-
摩通:澳门博彩股仍有上行空间 行业首选金沙中国-天天消息
摩通发表研究报告指,澳门六间博彩企业续牌并无惊喜,营运者一致承诺在未来十年内投资150亿美元,符合该行及市场预期,当中以金沙中国(1928 HK
-
全球讯息:智己汽车估值300亿11月销量仅608辆降29% CEO刘涛违章式“营销”被指漠视法律
背靠上汽集团、张江高科和阿里巴巴三大巨头,估值近300亿元的智己汽车却将一手好牌打得稀烂。 近日,上汽集团发布产销数据显示,智己汽车11
-
「大夫,我做手术的时候能看世界杯吗?」
「大夫,我做手术的时候能看世界杯吗?」
-
叮当钱包逾期14年还不起影响征信吗 热点
网贷逾期一般会上征信,有些借贷机构在用户逾期后一天后就会上报给征信机构,而有些借贷机构则是会在几天后上报给征信机构,因为有些借贷机构可
-
环球微动态丨北京丰台区倡议有闲暇时间的居民参与外卖配送服务
北京市丰台区商务局16日发出倡议,在个人及家庭允许的情况下,在确保自身身体健康的条件下,如近期未到岗工作或有闲暇时间,居民可以自主选择
-
喜报!信息学奥赛“省一”名单出炉!福建74人获一等奖
全国青少年信息学奥林匹克联赛(NOIP2022)获奖名单公布!福建74人获一等奖!
-
【天天新要闻】30亿灰飞烟灭,恒大汽车接连出问题,香港女首富被许家印坑惨了
恒大地产从2020年左右就开始频频爆雷,许家印甚至还倒欠了银行1 97万亿,一下子从声名显赫的地产大佬,变成如今要靠卖掉香港恒大总部大楼来还
-
飞行汽车已来,进入现实还需飞越重关
近日,全球首款载人级两座智能分体式飞行汽车工程样车在重庆发布,该样车由中国工程院院士项昌乐团队研发,北京理工大学、北京理工大学重庆创
-
世界今亮点!申联生物: 国浩律师(上海)事务所关于申联生物医药(上海)股份有限公司2022年第一次临时股东大会的法律意见书
国浩律师(上海)事务所 法律意见书 国浩律师(上海)事
-
永安药业董秘回复:公司是全球最大的牛磺酸生产基地,占50%左右的市场份额,拥有一定的市场话语权 全球热头条
永安药业(002365)12月15日在投资者关系平台上答复了投资者关心的问题。
-
环球讯息:哔哩哔哩-SW(09626.HK)授出196.74万份限制性股份单位
格隆汇12月15日丨哔哩哔哩-SW发布公告,2022年12月14日,公司根据2018年股份激励计划向140名承授人授出合共196 74万份限制性股份单位,涉及196
-
新化股份: 东方证券承销保荐有限公司关于浙江新化化工股份有限公司使用闲置募集资金进行现金管理的核查意见
新化股份:东方证券承销保荐有限公司关于浙江新化化工股份有限公司使用闲置募集资金进行现金管理的核查意见
-
2022年刑事附带民事公益诉讼的要件是怎样的-世界快资讯
1、民事公益诉讼是为了保护社会公共利益,对违反法律,侵害社会公共利益的行为,向人民法院提起诉讼,由法院按照民事诉讼程序依法审判并追究违
-
焦点速讯:罗博特科: 民生证券股份有限公司关于罗博特科智能科技股份有限公司关联交易的核查意见
罗博特科:民生证券股份有限公司关于罗博特科智能科技股份有限公司关联交易的核查意见
-
香港零售股涨幅居前,截至发稿,莎莎国际(00178.HK)涨13.61%,报1.92港元|环球热讯
香港零售股涨幅居前,截至发稿,莎莎国际(00178 HK)涨13 61%,报1 92港元;佐丹奴国际(00709 HK)涨6 59%,报1 78港元;六福集团(
-
天天热议:鹏欣资源(600490)12月12日主力资金净卖出1933.34万元
截至2022年12月12日收盘,鹏欣资源(600490)报收于3 15元,下跌3 96%,换手率1 3%,成交量25 91万手,成交额8272 36万元。12月
-
北京发布新冠病毒感染者用药目录(第一版)
最近,有不少市民购买的药物主要集中在“连花清瘟”“布洛芬”等国家第九版诊疗方案中推荐的几个有限的品种上。为此,多位药学、临床、中医...
-
全球微头条丨资金成本的计算公式是什么?
资金成本的计算公式为:资金成本率=资金占用费 所筹资金*100%得出。资金成本是企业筹集和使用资金而支付的各种费用,是资金使用者向资金所有者
-
焦点资讯:新媒股份: 关于股东股份减持计划时间过半的进展公告
证券代码:300770 证券简称:新媒股份 公告编号:2022-065
-
罗山县委书记周哲开展走访宣讲调研活动
10月17日上午,罗山县委书记周哲深入楠杆镇开展走访宣讲调研活动。县委书记周哲走进困难群众家中了解情况田成瑞 摄在楠杆镇石畈村,周哲走进困
-
河化股份(000953)12月7日主力资金净买入706.98万元:环球微速讯
截至2022年12月7日收盘,河化股份(000953)报收于6 57元,上涨2 82%,换手率3 04%,成交量11 12万手,成交额7237 78万元。12月
-
环球滚动:富吉瑞:11月25日接受机构调研,银河证券参与
2022年12月2日富吉瑞(688272)发布公告称公司于2022年11月25日接受机构调研,银河证券参与。具体内容如下:问:请公司目前在经营战略上有哪些调整吗
-
最高气温突破40℃!探访郑州高温热浪中的考古人
入夏以来最长、最强高温热浪过程,正在给河南带来一次大烤验。当考古遭遇热浪,却是有别于大家所理解的考古热。6月16日,郑州市最高气温突
-
朱祖国《山水牛闲图》亮相上海虹桥国际古玩城
弘扬上海文化,展示上海经典,是上海人民的风范,也是上海人民的自豪。在当下过中秋迎国庆之际,国画大家朱祖国绘画作品今起在上海虹桥国际