尚医通
版本:V1.0
登录需求 登录效果 登录需求- 登录采取弹出层的形式
- 登录方式:
- 手机号码+手机验证码
- 微信扫描
- 无注册界面,第一次登录根据手机号判断系统是否存在,如果不存在则自动注册
- 微信扫描登录成功必须绑定手机号码,即:第一次扫描成功后绑定手机号,以后登录扫描直接登录成功
- 网关统一判断登录状态,如何需要登录,页面弹出登录层
搭建过程参考service-hosp模块
1.2 修改配置1、修改pom.xml
service com.atguigu 0.0.1-SNAPSHOT 4.0.0 service_user com.atguigu service_cmn_client 0.0.1-SNAPSHOT
2、添加配置文件application.properties
# 服务端口
server.port=8203
# 服务名
spring.application.name=service-user
# 环境设置:dev、test、prod
spring.profiles.active=dev
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.44.165:3306/yygh_user?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root123
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/atguigu/yygh/user/mapper/xmlusermsm
public static ArrayList getRandom(List list, int n) {
Random random = new Random();
HashMap
6.3.4 完善登录service接口
修改UserInfoServiceImpl类登录方法,编写验证码校验
//校验校验验证码
String mobleCode = redisTemplate.opsForValue().get(phone);
if(!code.equals(mobleCode)) {
throw new YyghException(ResultCodeEnum.CODE_ERROR);
}
登录前端
7.1 封装api请求
创建api文件夹,创建/api/userInfo.js
import request from '@/utils/request'
const api_name = `/api/user`
export default {
login(userInfo) {
return request({
url: `${api_name}/login`,
method: `post`,
data: userInfo
})
}
}
创建/api/msm.js
import request from '@/utils/request'
const api_name = `/api/msm`
export default {
sendCode(mobile) {
return request({
url: `${api_name}/send/${mobile}`,
method: `get`
})
}
}
7.2安装cookie
登录成功,我们要把用户信息记录在cookie里面
命令行执行:
npm install js-cookie
7.3 添加登录组件登录层是一个公共层,因此我们把它放在头部组件里面
修改layouts/myheader.vue文件
{{ dialogAtrr.labelTips }}
0">{{ dialogAtrr.second }}s
重新发送
{{ dialogAtrr.loginBtn }}
第三方账号登录
手机短信验证码登录
微信扫一扫关注
“快速预约挂号”
扫一扫下载
“预约挂号”APP
xxxxxx官方指定平台
快速挂号 安全放心
说明:登录成功用户信息记录cookie
7.4 头部显示登录状态 7.4.1 获取登录信息
created() {
this.showInfo()
},
showInfo() {
let token = cookie.get('token')
if (token) {
this.name = cookie.get('name')
}
},
7.4.2 登录页面控制
帮助中心 登录/注册{{ name }} 实名认证 挂号订单 就诊人管理 退出登录
说明:
添加下拉列表事件处理:
loginMenu(command) {
if('/logout' == command) {
cookie.set('name', '', {domain: 'localhost'})
cookie.set('token', '', {domain: 'localhost'})
//跳转页面
window.location.href = '/'
} else {
window.location.href = command
}
},
登录全局事件
目前登录层在myheader组件里面,登录按钮也在同一个组件里面,我们点击登录,调用showLogin()方法即可
目前的问题是,我们在预约挂号页面,选择科室去挂号时我们需要判断当前是否登录,如果登录可以进入下一个页面;如果没有登录需要显示登录层,那么这个问题怎么解决呢,我们不能直接调用头部登录方法,我们目前的组件是包含在nuxt里面的
问题总是能够解决的,其实很简单,我们可以注册一个全局登录事件,当需要登录层是,我们发送一个登录事件,头部监听登录事件,然后我们触发登录按钮的点击事件即可打开登录层,下面我们来试试
8.1 头部注册和监听登录事件修改myheader.vue组件
1、引入Vue
import Vue from 'vue'
2、注册与监听事件
mounted() {
// 注册全局登录事件对象
window.loginEvent = new Vue();
// 监听登录事件
loginEvent.$on('loginDialogEvent', function () {
document.getElementById("loginDialog").click();
})
// 触发事件,显示登录层:loginEvent.$emit('loginDialogEvent')
}
8.2 预约挂号页面调整
修改/pages/hospital/_hoscode.vue组件
1、引入cookie
import cookie from 'js-cookie'
2、修改方法
schedule(depcode) {
// 登录判断
let token = cookie.get('token')
if (!token) {
loginEvent.$emit('loginDialogEvent')
return
}
window.location.href = '/hospital/schedule?hoscode=' + this.hospital.hoscode + "&depcode="+ depcode
},
说明:清除cookie,点击科室测试
myheader.vue完整代码
尚医通 预约挂号统一平台
搜索
帮助中心
登录/注册
{{ name }}
实名认证
挂号订单
就诊人管理
退出登录
{{ dialogAtrr.labelTips }}
0">{{ dialogAtrr.second }}s
重新发送
{{ dialogAtrr.loginBtn }}
第三方账号登录
手机短信验证码登录
微信扫一扫关注
“快速预约挂号”
扫一扫下载
“预约挂号”APP
xxxxxx官方指定平台
快速挂号 安全放心
用户认证与网关整合
思路:
- 所有请求都会经过服务网关,服务网关对外暴露服务,在网关进行统一用户认证;
- 既然要在网关进行用户认证,网关得知道对哪些url进行认证,所以我们得对ur制定规则
- Api接口异步请求的,我们采取url规则匹配,如:/apiauthinnerauth
private Long getUserId(ServerHttpRequest request) {
String token = "";
List
tokenList = request.getHeaders().get("token"); if(null != tokenList) { token = tokenList.get(0); } if(!StringUtils.isEmpty(token)) { return JwtHelper.getUserId(token); } return null; } 1.3 网关filter完整代码 @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { private AntPathMatcher antPathMatcher = new AntPathMatcher(); @Override public Mono2、调整前端yygh-sitefilter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String path = request.getURI().getPath(); System.out.println("==="+path); //内部服务接口,不允许外部访问 if(antPathMatcher.match("innerauth private Mono out(ServerHttpResponse response, ResultCodeEnum resultCodeEnum) { Result result = Result.build(null, resultCodeEnum); byte[] bits = JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8); DataBuffer buffer = response.bufferFactory().wrap(bits); //指定编码,否则在浏览器中会中文乱码 response.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); return response.writeWith(Mono.just(buffer)); } private Long getUserId(ServerHttpRequest request) { String token = ""; List tokenList = request.getHeaders().get("token"); if(null != tokenList) { token = tokenList.get(0); } if(!StringUtils.isEmpty(token)) { return JwtHelper.getUserId(token); } return null; } } 请求服务器端接口时我们默认带上token,需要登录的接口如果token没有或者token过期,服务器端会返回208状态,然后发送登录事件打开登录弹出层登录
修改utils/request.js文件
import axios from 'axios' import { MessageBox, Message } from 'element-ui' import cookie from 'js-cookie' // 创建axios实例 const service = axios.create({ baseURL: 'http://localhost', timeout: 15000 // 请求超时时间 }) // http request 拦截器 service.interceptors.request.use( config => { // token 先不处理,后续使用时在完善 //判断cookie是否有token值 if(cookie.get('token')) { //token值放到cookie里面 config.headers['token']=cookie.get('token') } return config }, err => { return Promise.reject(err) }) // http response 拦截器 service.interceptors.response.use( response => { //状态码是208 if(response.data.code === 208) { //弹出登录输入框 loginEvent.$emit('loginDialogEvent') return } else { if (response.data.code !== 200) { Message({ message: response.data.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(response.data) } else { return response.data } } }, error => { return Promise.reject(error.response) }) export default service



