来个黑黑的网站,wordpress还原站点,google网站提交入口,舆情报告2023背景及目的
之前做一个公司项目的时候甲方要求集成他们指定的CAS服务端实现登录#xff0c;要求不影响原有业务。 CAS服务端提供的文档都是基于前后端不分离的应用#xff0c;对前后端分离应用没有任何说明#xff0c;找官方人问也是爱答不理的#xff0c;近期正好有时间就…背景及目的
之前做一个公司项目的时候甲方要求集成他们指定的CAS服务端实现登录要求不影响原有业务。 CAS服务端提供的文档都是基于前后端不分离的应用对前后端分离应用没有任何说明找官方人问也是爱答不理的近期正好有时间就想着研究下这个集成过程。 于是有了这篇文章主要为了记录下集成过程和相关配置方便后续类似的对接。 当然也希望能帮助到需要的朋友。
CAS涉及到的角色
认证服务器客户端-API客户端-前台
整体流程梳理:
客户端请求地址A发现用户没有token,跳转到指定登录页面,地址类似/cas/login?servicexxxxx请求成功后会回调callbackUrl同时拼接ticket参数客户端发起ticket验证请求v2: /serviceValidate v3: /p3/serviceValidate验证成功后会回调到callbackUrl中同时在session中添加指定用户属性生成token并传递到前端或前端通过请求拿到token 思路一: 客户端拿到用户属性后根据用户生成token返回给前端,可以通过指定url拼接参数给到前端前端拦截后保存思路二: 客户端拿到用户属性后重定向到一个约定的前端地址前端在路由守卫中拦截该路径并在拦截到后发起getToken请求请求成功后 保存token等信息到缓存或者cookie即可。
实现过程
前期准备
cas认证服务端部署注册CAS协议的应用需要配置service/callbackUrl/clientNamevue-admin-template模板项目简单的springboot项目配置几个用于跳转的路由,在路由文件中添加 {path: /callback,hidden: true},{path: /tologin,hidden: true},这里只是为了路由守卫的拦截可以不写vue页面只需要在路由列表中添加定义即可亲测无误。
改造过程-前端
路由守卫文件 src/permission.js
import {getToken} from /utils/auth; // get token from cookie
import getPageTitle from /utils/get-page-title
import NProgress from nprogress; // progress bar
import nprogress/nprogress.css; // progress bar style
import router from ./router
import store from ./storeNProgress.configure({ showSpinner: false }) // NProgress Configurationconst whiteList [/login] // no redirect whitelist//是否支持cas登录的开关
const enableCasLogin truerouter.beforeEach(async(to, from, next) {// start progress barNProgress.start()// set page titledocument.title getPageTitle(to.meta.title)const hasToken getToken()//判断是否是去login页面if(to.path /tologin) {if(enableCasLogin){//实际访问的cas登录地址window.location.href http://localhost:9009/cas/login?servicehttp://localhost:8989/test1/indexredirect${to.params.redirect}} else {next(/login)}NProgress.done()} else if (whiteList.indexOf(to.path) ! -1) {next();} else if (to.path /callback) {if(!hasToken) {await store.dispatch(user/resetToken)}next(/)NProgress.done()} else {if(hasToken) {next()} else {if(to.path /) {next(/tologin)} else {next(/tologin?redirect${to.path})}}NProgress.done()}
})router.afterEach(() {// finish progress barNProgress.done()
})接口配置 /api/user.js
import request from /utils/requestexport function login(data) {return request({url: /auth/login,method: post,data})
}export function getCaptcha() {return request({url: /auth/captcha,method: get,})
}export function getCasToken() {return request({url: /auth/getToken,method: get,})
}export function logout() {return request({url: /vue-admin-template/user/logout,method: post})
}store配置 src/store/modules/user.js
import { getCasToken, login, logout } from /api/user
import { resetRouter } from /router
import { getToken, removeToken, setToken } from /utils/authconst getDefaultState () {return {token: getToken(),name: ,avatar: }
}const state getDefaultState()const mutations {RESET_STATE: (state) {Object.assign(state, getDefaultState())},SET_TOKEN: (state, token) {state.token token},SET_NAME: (state, name) {state.name name},SET_AVATAR: (state, avatar) {state.avatar avatar}
}const actions {// user loginlogin({ commit }, userInfo) {return new Promise((resolve, reject) {login(userInfo).then(response {const { data } responsecommit(SET_TOKEN, data.tokenType data.token)setToken(data.token)resolve()}).catch(error {reject(error)})})},// user logoutlogout({ commit, state }) {return new Promise((resolve, reject) {logout(state.token).then(() {removeToken() // must remove token firstresetRouter()commit(RESET_STATE)resolve()}).catch(error {reject(error)})})},// remove tokenresetToken({ commit }) {return new Promise(resolve {removeToken() // must remove token firstcommit(RESET_STATE)getCasToken().then(response {const { data } responsecommit(SET_TOKEN, data.tokenType data.token)commit(SET_NAME, data.user.username)setToken(data.token)resolve()}).catch(error {reject(error)})})}
}export default {namespaced: true,state,mutations,actions
}配置下接口地址 src/vue.config.js
module.exports {/*** You will need to set publicPath if you plan to deploy your site under a sub path,* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,* then publicPath should be set to /bar/.* In most cases please use / !!!* Detail: https://cli.vuejs.org/config/#publicpath*/publicPath: /,outputDir: dist,assetsDir: static,lintOnSave: process.env.NODE_ENV development,productionSourceMap: false,devServer: {port: port,open: true,overlay: {warnings: false,errors: true},// before: require(./mock/mock-server.js)proxy: {/dev-api: {target: http://localhost:8989,pathRewrite: { ^/dev-api: }}}},configureWebpack: {// provide the apps title in webpacks name field, so that// it can be accessed in index.html to inject the correct title.name: name,resolve: {alias: {: resolve(src)}}},chainWebpack(config) {// it can improve the speed of the first screen, it is recommended to turn on preloadconfig.plugin(preload).tap(() [{rel: preload,// to ignore runtime.js// https://github.com/vuejs/vue-cli/blob/dev/packages/vue/cli-service/lib/config/app.js#L171fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],include: initial}])// when there are many pages, it will cause too many meaningless requestsconfig.plugins.delete(prefetch)// set svg-sprite-loaderconfig.module.rule(svg).exclude.add(resolve(src/icons)).end()config.module.rule(icons).test(/\.svg$/).include.add(resolve(src/icons)).end().use(svg-sprite-loader).loader(svg-sprite-loader).options({symbolId: icon-[name]}).end()config.when(process.env.NODE_ENV ! development,config {config.plugin(ScriptExtHtmlWebpackPlugin).after(html).use(script-ext-html-webpack-plugin, [{// runtime must same as runtimeChunk name. default is runtimeinline: /runtime\..*\.js$/}]).end()config.optimization.splitChunks({chunks: all,cacheGroups: {libs: {name: chunk-libs,test: /[\\/]node_modules[\\/]/,priority: 10,chunks: initial // only package third parties that are initially dependent},elementUI: {name: chunk-elementUI, // split elementUI into a single packagepriority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or apptest: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm},commons: {name: chunk-commons,test: resolve(src/components), // can customize your rulesminChunks: 3, // minimum common numberpriority: 5,reuseExistingChunk: true}}})// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunkconfig.optimization.runtimeChunk(single)})}
}改造过程-后端
添加依赖 pom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.7.13/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcom.zjtx.tech/groupIdartifactIdauth-cas-api/artifactIdversion0.0.1-SNAPSHOT/versionnameauth-cas-api/namedescriptionCAS API/descriptionpropertiesjava.version1.8/java.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdnet.unicon.cas/groupIdartifactIdcas-client-autoconfig-support/artifactIdversion2.3.0-GA/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build
/project依赖中主要添加的是cas-client-autoconfig-support这个jar包提供了cas需要的一些配置和拦截器
配置文件添加
server:port: 8989
cas:# 配置实际的cas地址server-url-prefix: http://localhost:9009/cas# 配置实际的cas登录地址server-login-url: http://localhost:9009/cas/loginclient-host-url: http://localhost:8989/# 这里可以选择cas 和 cas3 区别是请求的部分地址不一样如ticket验证的接口validation-type: cas
# 拦截的URL地址authentication-url-patterns:- /*
spring:jackson:serialization:FAIL_ON_EMPTY_BEANS: false获取token的controller
src/main/java/com/zjtx/tech/controller/AuthController.java
package com.zjtx.tech.contorller;import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;RestController
RequestMapping(/auth)
public class AuthController {GetMapping(getToken)public ResultBeanTokenUser getToken(HttpServletRequest request){Assertion assertion (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);System.out.println(assertion assertion.getPrincipal().getAttributes());String username assertion.getPrincipal().getName();System.out.println(username);//这里仅为了演示直接new了一个简单对象返回给前端SimpleUserBean user new SimpleUserBean(1, username, 123456, 456789);return new ResultBean(200, success, new TokenUser(user, 123456, Bearer));}}回调接口对应的controller
src/main/java/com/zjtx/tech/controller/TestController.java
package com.zjtx.tech.contorller;import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;RestController
public class TestController {GetMapping(test1/index)public void index(HttpServletRequest request, HttpServletResponse resp) throws IOException {String token request.getParameter(congress);System.out.println(congress : token);Assertion assertion (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);System.out.println(assertion assertion.getPrincipal().getAttributes());String username assertion.getPrincipal().getName();System.out.println(username);resp.sendRedirect(http://localhost:9528/#/callback);}GetMapping(test1/index1)public String index1(HttpServletRequest request) {String token request.getParameter(token);System.out.println(token : token);Assertion assertion (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);String username assertion.getPrincipal().getName();System.out.println(username);return test index cas拦截正常,登录账号: username;}/*** 不走cas认证无法获取登录信息** param request* return*/GetMapping(test1/index2)public String index2(HttpServletRequest request) {return cas 未拦截;}
}涉及到的简单bean就不在此列举了。
测试过程
启动前后端及认证服务器项目访问前端地址 会跳转到认证服务器定义的loginUrl登录完成后会调用http://localhost:9528/#/callback,被路由守卫拦截后进行token的获取和保存保存完成后进入首页
总结
本文主要记录了前后端分离场景下集成CAS单点登录的基本流程。 作为记录的同时也希望能帮助到需要的朋友有任何疑问欢迎留言评论。 创作不易欢迎一键三连~ 文章转载自: http://www.morning.spsqr.cn.gov.cn.spsqr.cn http://www.morning.lnrhk.cn.gov.cn.lnrhk.cn http://www.morning.wzjhl.cn.gov.cn.wzjhl.cn http://www.morning.tfrmx.cn.gov.cn.tfrmx.cn http://www.morning.ckwxs.cn.gov.cn.ckwxs.cn http://www.morning.mlcnh.cn.gov.cn.mlcnh.cn http://www.morning.zwtp.cn.gov.cn.zwtp.cn http://www.morning.ndnhf.cn.gov.cn.ndnhf.cn http://www.morning.jppdk.cn.gov.cn.jppdk.cn http://www.morning.qlznd.cn.gov.cn.qlznd.cn http://www.morning.bsplf.cn.gov.cn.bsplf.cn http://www.morning.bmmhs.cn.gov.cn.bmmhs.cn http://www.morning.kwksj.cn.gov.cn.kwksj.cn http://www.morning.bmtyn.cn.gov.cn.bmtyn.cn http://www.morning.dzrcj.cn.gov.cn.dzrcj.cn http://www.morning.pltbd.cn.gov.cn.pltbd.cn http://www.morning.scjtr.cn.gov.cn.scjtr.cn http://www.morning.kpzbf.cn.gov.cn.kpzbf.cn http://www.morning.mksny.cn.gov.cn.mksny.cn http://www.morning.dwfzm.cn.gov.cn.dwfzm.cn http://www.morning.rkdw.cn.gov.cn.rkdw.cn http://www.morning.gkktj.cn.gov.cn.gkktj.cn http://www.morning.rwqj.cn.gov.cn.rwqj.cn http://www.morning.qjlnh.cn.gov.cn.qjlnh.cn http://www.morning.psqs.cn.gov.cn.psqs.cn http://www.morning.gtnyq.cn.gov.cn.gtnyq.cn http://www.morning.qfdyt.cn.gov.cn.qfdyt.cn http://www.morning.pfnwt.cn.gov.cn.pfnwt.cn http://www.morning.divocn.com.gov.cn.divocn.com http://www.morning.rpgdd.cn.gov.cn.rpgdd.cn http://www.morning.rhkq.cn.gov.cn.rhkq.cn http://www.morning.lgnrl.cn.gov.cn.lgnrl.cn http://www.morning.zcqgf.cn.gov.cn.zcqgf.cn http://www.morning.rfwrn.cn.gov.cn.rfwrn.cn http://www.morning.tngdn.cn.gov.cn.tngdn.cn http://www.morning.knpmj.cn.gov.cn.knpmj.cn http://www.morning.fpkdd.cn.gov.cn.fpkdd.cn http://www.morning.mmtjk.cn.gov.cn.mmtjk.cn http://www.morning.hqbk.cn.gov.cn.hqbk.cn http://www.morning.kybjr.cn.gov.cn.kybjr.cn http://www.morning.qyjqj.cn.gov.cn.qyjqj.cn http://www.morning.nlcw.cn.gov.cn.nlcw.cn http://www.morning.gwqcr.cn.gov.cn.gwqcr.cn http://www.morning.prgyd.cn.gov.cn.prgyd.cn http://www.morning.3dcb8231.cn.gov.cn.3dcb8231.cn http://www.morning.tbjb.cn.gov.cn.tbjb.cn http://www.morning.rfpxq.cn.gov.cn.rfpxq.cn http://www.morning.xflzm.cn.gov.cn.xflzm.cn http://www.morning.rkypb.cn.gov.cn.rkypb.cn http://www.morning.rglzy.cn.gov.cn.rglzy.cn http://www.morning.xldpm.cn.gov.cn.xldpm.cn http://www.morning.stpkz.cn.gov.cn.stpkz.cn http://www.morning.plcyq.cn.gov.cn.plcyq.cn http://www.morning.blqsr.cn.gov.cn.blqsr.cn http://www.morning.rbhcx.cn.gov.cn.rbhcx.cn http://www.morning.rbnp.cn.gov.cn.rbnp.cn http://www.morning.kmqlf.cn.gov.cn.kmqlf.cn http://www.morning.rcjyc.cn.gov.cn.rcjyc.cn http://www.morning.wzknt.cn.gov.cn.wzknt.cn http://www.morning.xlndf.cn.gov.cn.xlndf.cn http://www.morning.fkgct.cn.gov.cn.fkgct.cn http://www.morning.qnzgr.cn.gov.cn.qnzgr.cn http://www.morning.wnbqy.cn.gov.cn.wnbqy.cn http://www.morning.sgrwd.cn.gov.cn.sgrwd.cn http://www.morning.bgqr.cn.gov.cn.bgqr.cn http://www.morning.skmpj.cn.gov.cn.skmpj.cn http://www.morning.qbnfc.cn.gov.cn.qbnfc.cn http://www.morning.pwrkl.cn.gov.cn.pwrkl.cn http://www.morning.yltnl.cn.gov.cn.yltnl.cn http://www.morning.zfzgp.cn.gov.cn.zfzgp.cn http://www.morning.xsfny.cn.gov.cn.xsfny.cn http://www.morning.rhkgz.cn.gov.cn.rhkgz.cn http://www.morning.gjcdr.cn.gov.cn.gjcdr.cn http://www.morning.dbsch.cn.gov.cn.dbsch.cn http://www.morning.lggng.cn.gov.cn.lggng.cn http://www.morning.jzlkq.cn.gov.cn.jzlkq.cn http://www.morning.jrpmf.cn.gov.cn.jrpmf.cn http://www.morning.lbywt.cn.gov.cn.lbywt.cn http://www.morning.bchfp.cn.gov.cn.bchfp.cn http://www.morning.xscpq.cn.gov.cn.xscpq.cn