一、背景介绍

公司现有一个ssh框架的旧系统,想要转型使用前后端分离vue+springboot的新框架。由于一些原因,无法完全转型,所以考虑新增的业务需求,使用在旧系统中嵌套新系统页面的方式,之后新需求就可以完全使用前后端分离的新框架了。

二、解决方案

用户登录旧系统,展示的菜单是按照新系统开发的前端工程,然后页面上所有操作都与springboot工程接口通信。springboot系统与旧ssh系统操作同一数据库。

三、登录认证

此方案分为ssh系统、vue前端系统以及springboot系统。用户登录的是ssh旧系统,所有后面的请求需要进行登录的认证。方案是ssh系统登录后,生成token,存在localstorage中;然后展示vue前端系统时,将token传递过去;后面调用springboot接口时,将token带在请求的请求头中,这样所有请求都会带着token,即可进行登录身份认证。代码如下:

ssh系统中使用JWT生成token:

         String token = this.getToken(userVw.getUser());getRequest().setAttribute("token", token);/*** 生成token* @param user* @return*/public String getToken(User user) {/*** token默认有效时间 1天*/Long jwtTimeOut = 86400L;Date date = new Date(System.currentTimeMillis() + jwtTimeOut);String token="";token= JWT.create().withAudience(user.getId().toString())// 将 user id 保存到 token 里面
//              .withExpiresAt(date).sign(Algorithm.HMAC256(user.getPasswd()));// 以 password 作为 token 的密钥return token;}

然后跳转vue前台系统时,将token传递过去,代码如下:

var token = localStorage.getItem("token");url=url+"&token="+tokenconsole.log(url);self.parent.parent.document.getElementById("mainFrame").src = url;

vue前端系统:

router.beforeEach((to, from, next) => {debuggervar token = to.query.token;localStorage.setItem('logintoken', token)
}

请求的请求头中添加上token

const req = (method, url, params) => {return axios({method: method,url: url,headers: {'Content-Type': 'application/x-www-form-urlencoded',token: localStorage.getItem('logintoken')},data: params,traditional: true,transformRequest: [function (data) {let ret = ''for (let it in data) {ret +=encodeURIComponent(it) +'=' +encodeURIComponent(data[it]) +'&'}return ret}]}).then(res => res.data);
};

springboot后台,添加依赖:

        <!--jwt--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency>

配置拦截器:

package com.nomen.ctms.efms.config;import com.nomen.ctms.efms.base.interceptor.AuthenticationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class IntercepterConfig implements WebMvcConfigurer {/*** 对所有请求增加拦截器* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**");}@Beanpublic AuthenticationInterceptor authenticationInterceptor(){return new AuthenticationInterceptor();}
}

拦截器拦截所有请求:

package com.nomen.ctms.efms.base.interceptor;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.nomen.ctms.efms.base.annotation.PassToken;
import com.nomen.ctms.efms.base.annotation.NeedLoginToken;
import com.nomen.ctms.efms.system.user.entity.User;
import com.nomen.ctms.efms.system.user.service.UserService;
import com.nomen.ctms.efms.utils.CurrentUserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;public class AuthenticationInterceptor implements HandlerInterceptor {@AutowiredUserService userService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String token = request.getHeader("token");//如果不是映射到方法直接通过if(!(handler instanceof HandlerMethod)){return true;}HandlerMethod handlerMethod = (HandlerMethod)handler;Method method = handlerMethod.getMethod();//检查方法是否有通过验证的注释passtoken,有则跳过认证if(method.isAnnotationPresent(PassToken.class)){PassToken passToken = method.getAnnotation(PassToken.class);if(passToken.required()){return true;}}//检查有没有需要用户权限的注解if(method.isAnnotationPresent(NeedLoginToken.class)){NeedLoginToken annotation = method.getAnnotation(NeedLoginToken.class);if(annotation.required()){//执行认证if(token==null){throw new RuntimeException("无token,请重新登录");}}
//            获取token中的userIdString userId;try{userId = JWT.decode(token).getAudience().get(0);}catch (JWTDecodeException j){throw new RuntimeException("401");}User user = userService.getById(Long.valueOf(userId));CurrentUserUtil.addCurrentUser(user);if (user == null) {throw new RuntimeException("用户不存在,请重新登录");}
//            验证tokenJWTVerifier verifier = JWT.require(Algorithm.HMAC256(user.getPasswd())).build();try {DecodedJWT verify = verifier.verify(token);System.out.println(verify);} catch (JWTVerificationException e) {e.printStackTrace();throw new RuntimeException("401",e);}return true;}return true;}}

创建注解类:

package com.nomen.ctms.efms.base.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 需要登录才能进行操作的注解* @Target:注解的作用目标* @Target(ElementType.TYPE)——接口、类、枚举、注解* @Target(ElementType.METHOD)——方法** @Retention:注解的保留位置* RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。**/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLoginToken {boolean required() default true;
}
package com.nomen.ctms.efms.base.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 用来跳过验证的注解* @Target:注解的作用目标* @Target(ElementType.TYPE)——接口、类、枚举、注解* @Target(ElementType.METHOD)——方法** @Retention:注解的保留位置* RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {boolean required() default true;
}

在需要认证的接口上添加@NeedLoginToken注解:

  @NeedLoginToken@RequestMapping(value = "/list",method = RequestMethod.POST)public ResponseResult getTemplate(Page page, DocTemplate template){ResponseResult responseResult = new ResponseResult();User currentUser = CurrentUserUtil.getCurrentUser();System.out.println(currentUser.getUserId());IPage iPage = this.templateService.queryTemplate(page, template);List records = iPage.getRecords();responseResult.setData(records);responseResult.setSuccess(true);responseResult.setTotal(iPage.getTotal());return responseResult;}

四、总结

由于本人经验也不是很充足,目前也只想到了这个方案,有什么问题或者有更好的方法,还请大佬们多多指教。

记录一种ssh旧系统和前后端分离新系统结合的解决方案,以及两系统间通过token进行认证的方式相关推荐

  1. 权限系统(前后端分离)

    权限系统(前后端分离) B站视频教程 以下是总结的笔记.仅供参考. 采用的技术栈:本课程采用主流的技术栈实现,Mysq|数据库,SpringBoot2+Mybatis Plus后端,redis缓存,安 ...

  2. 采用SpringBoot、MyBatis-Plus 、Security框架,开发的一套权限系统,实现前后端分离,完善的代码生成机制

    项目说明 harry 采用SpringBoot.MyBatis-Plus .Security框架,开发的一套权限系统,实现前后端分离,完善的代码生成机制.Harry Gitee地址 harry-vue ...

  3. 【开源】物联网智慧消防云平台系统,前后端分离,微服务框架带文档,源码分享

    [开源]IoT-智慧消防云平台系统,前后端分离微服务框架源码带文档 基于微服务的物联网消防云平台 开发环境:java+mysql+redis+rabbitmq+elasticsearch 源码类型:全 ...

  4. 使用layuimini模块快速开发java后台系统模板(前后端分离)

    使用layuimini模块快速开发后台系统模板(前后端分离) 下面已仓库管理系统为例(下面源码可自己下载来看) 1.登录界面login.html 下面的验证码使用的是Hutool 来实现的(Hutoo ...

  5. 阿里云视频上传视频获取进度条问题(使用session方案,获取进度一直为0的解决方案)补充:前后端分离项目中获取进度解决方案

    1.场景描述: 之前用阿里云上传视频,前端反应上传视频经常出现获取视频url失败问题.但是接口我测过很多遍都是没有问题的.后台这边提供了一个视频上传的接口返回一个videoId,还提供了一个根据vid ...

  6. 前后端分离与跨域的解决方案(CORS的原理)

    前后端分离 前后端分离的好处 最大的好处就是前端JS可以做很大部分的数据处理工作,对服务器的压力减小到最小. 后台错误不会直接反映到前台,错误接秒较为友好. 由于后台是很难去探知前台页面的分布情况,而 ...

  7. pc网站调用微服务器,【微服务】前后端分离-跨域问题和解决方案

    跨域问题存在的原因 跨域问题的根本原因:因为浏览器收到同源策略的限制,当前域名的js只能读取同域下的窗口属性.什么叫做同源策略?就是不同的域名, 不同端口, 不同的协议不允许共享资源的,保障浏览器安全 ...

  8. php 跨域 验证_php 前后端分离开发进行跨域请求时ajax发送验证参数token的header头解决方法...

    php前后端分离开发中要实现前后端参数信息交互,必须解决token标识验证问题. 步骤如下: 1.前端ajax发送请求时,要设置一个自定义header头.代码如下: $.ajax({ url:&quo ...

  9. java基于Springboot+vue的影城电影院购票选座系统 elementui 前后端分离

    本论文主要论述了如何使用JAVA语言开发一个影城管理系统 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发.在引言中,作者将论述影城管理系统的当前背景以及 ...

最新文章

  1. oracle删除日志文件
  2. docker mysql 主从库配置
  3. 使用 TensorFlow 的公司
  4. 金蝶mysql_金蝶财务软件中的数据库如何进入?
  5. AI算法连载16:统计之聚类
  6. 什么是devops开发运维_为什么假设驱动的开发是DevOps的关键
  7. GB 2312 编码
  8. 基于英雄联盟寻路背景的A星算法及python实现
  9. 网页英文 错位_浏览器不兼容,网页错位的简单解决方法
  10. C - Quick Sort (one of the simplest)
  11. 利用迅捷画图绘制环型网络拓扑图操作方法介绍
  12. 项目管理5阶段|一位高级项目经理的4年项目经验分享
  13. Java远程屏幕监控案例
  14. HTML相对路径的写法
  15. D. Cloud of Hashtags(逆向贪心)
  16. 2021年全球运动文胸收入大约10690百万美元,预计2028年达到21150百万美元
  17. 从CDN到边缘计算,近水楼台是否先得月?
  18. ArcGIS水文分析提取河网及流域
  19. Spark之wordCount合集
  20. UE4虚幻引擎入门的一些知识

热门文章

  1. 计算机考试没关掉Word交卷,计算机二级MS OFFICE考试,在我交卷的时候总是提示word没关闭等,是怎么回事?...
  2. python五子棋人机对战_Python五子棋
  3. CRC校验的理解和计算过程
  4. unity3D 贴图和高亮效果
  5. VS Opencv 字符模板匹配小实例
  6. 小鼠脑立体定位图谱_脑动脉瘤动物模型
  7. matlab共面波导阻抗计算公式,共面波导、微带线、带状线和其他平面传输线之间的区别...
  8. java 移动平均_移动平均法计算企业职工养老金替代率的JAVA实现
  9. 编写一个判断完数的函数。完数是指一个数恰好等于它的因子之和,如6=1+2+3,6就是完数。
  10. COCO Detection Challenge