实际开发中,关于单点登录之前后端分离

  • Post author:
  • Post category:其他




实际开发中,关于单点登录之前后端分离

单点登录,简单来说,就是多个相关系统使用同一个登录页,一次登录,多系统获取Token



步骤一、重新编辑登录页面html文件,并发给后端

登录页面样式一样,只是vue文件,变为html文件,并交给后端人员部署到后台上,可以去掉之前带有表单的vue页面

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登录</title>
<style>
*{
  margin:0;
  padding:0;
  box-sizing:border-box;
}
body {
    background: url(img/bg.png) no-repeat center 0px fixed;
    background-size: cover;
    font-family: "微软雅黑", sans-serif;
}
.login { 
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -150px 0 0 -150px;
    width:300px;
    height:300px;
}
.login h1 { 
    color:#555555;
    text-shadow: 0px 10px 10px #CDC673;
    letter-spacing:2px;text-align:center;
    margin-bottom:20px;
}
input{
    padding:10px;
    width:100%;
    color:white;
    margin-bottom:10px;
    background-color:#555555;
    border: 1px solid black;
    border-radius:5px;
    letter-spacing:2px;
}
form button{
    width:100%;
    padding:10px;
    margin-bottom:10px;
    background-color:#CDC673;
    border:1px solid black;
    border-radius:5px;
    cursor:pointer; 
}                                                                                                                                       
</style>
</head>
<body>
<div class="login">
    <h1>单点登录系统</h1>
  	<!-- 这块必须是表单元素,配置属性不要变 -->
   <form action="/login" method="post">
    <input type="text" name="username" placeholder="用户名" required="required">
    <input type="password" name="password" placeholder="密  码" required="required">
    <button type="submit">登录</button>
  </form>
</div>
</body>
</html>



步骤二、使用前置导航守卫

使用前置导航守卫,每一次跳转页面,都要判断token

import { toSso } from '@/api/user';
import store from '@/store';
import { getCookie } from '@/tool/cookie';
import { get } from "@/api/api";
import { getToken } from "@/api/api.js";
// 获取地址栏的code【使用后端给的code值,调用getToken接口】
function getQueryVariable(variable) {
  const query = window.location.search.substring(1); // 从问号 (?) 开始的 URL(查询部分)
  const vars = query.split('&');
  for (let i = 0; i < vars.length; i++) {
    const pair = vars[i].split('=');
    if (pair[0] === variable) {
      return pair[1];
    }
  }
  return '';
};
// 前置导航守卫
router.beforeEach(async (to, from, next) => {
  // cookie的设置,是后端设置的,前端只需要获取,或者置空
  const accessToken = getCookie('access_token');
  if (accessToken) {
    const userInfo = store.state.user.userDesc.id;
    if (userInfo) {
      next();
    } else {
      // 系统第一次:调用获取用户信息的接口
      const res = await get('/sso/user/get');
      // 保存用户信息到Vuex
      store.commit("user/setUser", res.data);
      next();
    }
  } else {
    // 调用toSso之前是没有code的
    const code = getQueryVariable('code');
    if (code) {
      // token调用成功  才能调用用户信息接口
      let dataRes = await getToken(code); 
      // 记录地址信息  
      window.location = sessionStorage.getItem('visitUri');
    } else {
        // 如果没有accessToken,跳转到单点系统的登录页  获取code
       toSso();
    }
    
	
	// const whiteList = ['/home'];
	// 如下是当  摇摆页是:没有表单的登录页
	
	//if (whiteList.indexOf(to.path) !== -1) {
      //next();
    //} else {
      //toSso();
    //}
  }
});



步骤三、toSso方法

// 地址都是和后端保存一致的
import _config from './http.config';
const ssoUri = _config.ssoUri;
const userInfoUri = _config.userInfoUri;
const tokenUri = _config.tokenUri;
const clientId = _config.clientId;
const callbackUri = _config.callbackUri;

// http://192.168.102.59:8080/#/index   注意:前端的#要转义成:%23
// callbackUri: 'http://192.168.102.59:8080/%23/index',
function getAuthorizeUri(state) {
  // 为sso函数提供地址:
  return (
    ssoUri +
    'authorize?client_id=' +
    clientId +
    '&scope=all&response_type=code&redirect_uri=' +
    callbackUri   // 单点登录摇摆页/重定向页面(没有表单的登录页  或者  系统首页)
  );
}
export function toSso() {
  sessionStorage.setItem('visitUri', window.location.href); // 页面临时缓存数据
  window.location.href = getAuthorizeUri();
}



步骤四:获取cookie的方式

/**
 * 设置cookie
 * @param name 字段名
 * @param value 值
 * @param seconds 失效时长
 */
 export function setCookie(name, value, seconds) {
    seconds = seconds || 0; // seconds有值就直接赋值,没有为0
    let expires = '';
    if (seconds !== 0) {
      // 设置cookie生存时间
      const date = new Date();
      date.setTime(date.getTime() + seconds * 1000);
      expires = '; expires=' + date['toGMTString']();
    }
    document.cookie = name + '=' + escape(value) + expires + '; path=/';
  }
  
  /**
   * 获取cookie
   * @param name 字段名
   */
  export function getCookie(name) {
    if (document.cookie.length > 0) {
      let start = document.cookie.indexOf(name + '=');
      if (start !== -1) {
        start = start + name.length + 1;
        let end = document.cookie.indexOf(';', start);
        if (end === -1) end = document.cookie.length;
        return unescape(document.cookie.substring(start, end)).replace(/'/g, '');
      }
    }
    return null;
  }



步骤五、请求拦截封装

import axios from "axios";
import store from '@/store';
import { getCookie } from '@/tool/cookie';
const $http = axios.create({
    baseURL: './',
    timeout: 5000,
    retry: 1,
    retryDelay: 1000,
    withCredentials: true,
})
$http.interceptors.request.use( 
    (config) => {
      if (config.url === '/system/login/captcha') return config;
      if (config.url === '/auth/oauth/token') {
        const str = 'lin:123123';
        const str64 = Buffer.from(str).toString('base64');
        config.headers.Authorization = 'Basic ' + str64;
        return config;
      }
      const accessToken = getCookie('access_token');
      if (accessToken) {
        if (!config.url.includes('http://')) {
          // 让每个请求携带自定义token 请根据实际情况自行修改
          config.headers['Authorization'] = 'Bearer ' + accessToken; 
          config.headers['Access-Control-Allow-Origin'] = '*';
          config.headers['userId'] = store.state.user.userDesc.id
          return Promise.resolve(config);
        }
      }
      return config;
    },
    (error) => {
      Promise.reject(error);
    }
);

export default $http;



关于集成单点后,退出登录方式改变

// window.customizeConfig.callbackUri  摇摆页(没有表单的登录页  或者  首页)
signOut: `/logout?redirect_uri=${window.customizeConfig.callbackUri}`,
outLogin() {
  // 清除用户信息
  this.setUser({});  
  // 清除cookie
  setCookie('access_token','',-1);
  // window.customizeConfig.ssoAddr : 后端给的地址
  window.location.href = window.customizeConfig.ssoAddr + this.url.signOut;  // 此时会自动跳转到登录页
},



版权声明:本文为weixin_44224921原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。