医院项目-预约挂号-第八部分手机登录

一、登录需求

1、登录效果

在这里插入图片描述

2、登录需求
1,登录采取弹出层的形式
2,登录方式:
(1)手机号码+手机验证码
(2)微信扫描
3,无注册界面,第一次登录根据手机号判断系统是否存在,如果不存在则自动注册
4,微信扫描登录成功必须绑定手机号码,即:第一次扫描成功后绑定手机号,以后登录扫描直接登录成功
5,网关统一判断登录状态,如何需要登录,页面弹出登录层

二、登录

1,搭建service-user模块

1.1 搭建service-user模块
搭建过程参考service-hosp模块

1.2 修改配置
1、修改pom.xml
在这里插入图片描述

2、添加配置文件application.properties

在这里插入图片描述

# 服务端口
server.port=8203
# 服务名
spring.application.name=service-user

# 环境设置:dev、test、prod
spring.profiles.active=dev

# mysql数据库连接,mysql8的这里需要修改
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

# mysql8数据库连接
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://127.0.0.1:3306/yygh_user?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=UTC
#spring.datasource.username=root123
#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/fan/yygh/user/mapper/xml/*.xml

注意创建好数据库yygh_user和数据;

在这里插入图片描述

1.3 启动类

在这里插入图片描述

@SpringBootApplication
@ComponentScan(basePackages = "com.atguigu")
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.atguigu")
@MapperScan(basePackages = "com.fan.yygh.user.mapper")
public class ServiceUserApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceUserApplication.class, args);
    }
}

1.4配置网关
在网关的微服务中修改yml/application.properties:

#设置路由id
spring.cloud.gateway.routes[2].id=service-user
#设置路由的uri
spring.cloud.gateway.routes[2].uri=lb://service-user
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[2].predicates= Path=/*/user/**

在这里插入图片描述

2、添加用户基础类

2.1 添加model
说明:由于实体对象没有逻辑,我们已经统一导入
com.fan.yygh.model.user.UserInfo

2.2 添加Mapper
1,添加com.fan.yygh.user.UserInfoMapper

public interface UserInfoMapper extends BaseMapper<UserInfo> {
}

2,添加UserInfoMapper.xml,相当于servers的实现类一样

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fan.yygh.user.mapper.UserInfoMapper">

</mapper>

在这里插入图片描述

2.3 添加service接口及实现类

1、添加com.fan.yygh.user.service.UserInfoService接口

public interface UserInfoService extends IService<UserInfo> {
}

2、添加com.fan.yygh.user.service.impl.UserInfoServiceImpl接口实现

@Service
public class UserInfoServiceImpl extends
        ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
        
         @Resource
    private UserInfoMapper userInfoMapper;
}

2.4 添加controller
添加com.fan.yygh.user.api.UserInfoApiController类

@RestController
@RequestMapping("/api/user")
public class UserInfoApiController {

    @Autowired
    private UserInfoService userInfoService;
}

在这里插入图片描述

3、后台登录api接口

登录的后台:
3.1 添加controller接口

1、在UserInfoApiController类添加方法:

在这里插入图片描述

实现类:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.fan.yygh.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fan.yygh.common.exception.YyghException;
import com.fan.yygh.common.result.ResultCodeEnum;
import com.fan.yygh.model.user.UserInfo;
import com.fan.yygh.user.mapper.UserInfoMapper;
import com.fan.yygh.user.service.UserInfoService;
import com.fan.yygh.vo.user.LoginVo;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@Service //先继承《M是mapper,T是实体类》后实现
public class UserInfoImpl extends ServiceImpl<UserInfoMapper, UserInfo>
        implements UserInfoService {
    @Resource
    private UserInfoMapper userInfoMapper;

    //用户手机号登录接口
    @Override
    public Map<String, Object> loginUser(LoginVo loginVo) {
        //从vo中获取参数
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        //参数校验
        if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
            throw new YyghException(ResultCodeEnum.PARAM_ERROR);//ResultCodeEnum枚举类
        }
        //TODO 校验校验验证码
        //判断是否第一次登录,根据手机号查询数据库,如果不存在相同的手机号就是第一次登录
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",phone);
        UserInfo userInfo = baseMapper.selectOne(wrapper);
        if(userInfo == null){//第一次使用这个手机号登录
            //添加信息到数据库
            userInfo = new UserInfo();
            userInfo.setName("");
            userInfo.setPhone(phone);
            userInfo.setStatus(1);//设置可用
            //this.save(userInfo);//保存到数据库
            baseMapper.insert(userInfo);
        }
        //返回给页面的map信息
        HashMap<String, Object> map = new HashMap<>();
        String name = userInfo.getName();
        if (StringUtils.isEmpty(name)) {//如果名字为空
            name = userInfo.getNickName();//用昵称代替名字
        }
        if(StringUtils.isEmpty(name)){
            name = userInfo.getPhone();//如果名字为空,用手机号代替名字
        }
        map.put("name",name);//返回name和token
        map.put("token","");
        return null;
    }
}

5、生成token

5.1 JWT介绍

JWT工具
JWT(Json Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上

JWT最重要的作用就是对 token信息的防伪作用。

JWT的原理,
一个JWT由三个部分组成:公共部分、私有部分、签名部分。最后由这三者组合进行base64编码得到JWT。

在这里插入图片描述

在这里插入图片描述

1、公共部分
主要是该JWT的相关配置参数,比如签名的加密算法、格式类型、过期时间等等。
Key=ATGUIGU

2、私有部分
用户自定义的内容,根据实际需要真正要封装的信息。
userInfo{用户的Id,用户的昵称nickName}

3、签名部分
SaltiP: 当前服务器的Ip地址!{linux 中配置代理服务器的ip}
主要用户对JWT生成字符串的时候,进行加密{盐值}
最终组成 key+salt+userInfo token!

base64编码,并不是加密,只是把明文信息变成了不可见的字符串。但是其实只要用一些工具就可以把base64编码解成明文,所以不要在JWT中放入涉及私密的信息。

5.2 集成JWT
1,在common-util模块pom.xml添加依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
</dependency>

版本已在yygh-parent父模块pom.xml添加;

在这里插入图片描述

2,在common-util模块编写JwtHelper类

放在helper包下:

在这里插入图片描述

JwtHelper类代码:

package com.fan.yygh.helper;

import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;

import java.util.Date;

public class JwtHelper {
    //过期时间
    private static long tokenExpiration = 24*60*60*1000;
    //签名秘钥
    private static String tokenSignKey = "123456";
    //根据参数生成token
    public static String createToken(Long userId, String userName) {
        String token = Jwts.builder()
                .setSubject("YYGH-USER")
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                .claim("userId", userId)
                .claim("userName", userName)
                .signWith(SignatureAlgorithm.HS512, tokenSignKey)
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }
    //根据token字符串得到用户id
    public static Long getUserId(String token) {
        if(StringUtils.isEmpty(token)) return null;
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        Integer userId = (Integer)claims.get("userId");
        return userId.longValue();
    }
    //根据token字符串得到用户名
    public static String getUserName(String token) {
        if(StringUtils.isEmpty(token)) return "";
        Jws<Claims> claimsJws 
= Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("userName");
    }
    public static void main(String[] args) {
        String token = JwtHelper.createToken(1L, "55");
        System.out.println(token);
        System.out.println(JwtHelper.getUserId(token));
        System.out.println(JwtHelper.getUserName(token));
    }
}

5.3 完善登录service接口
修改UserInfoServiceImpl类登录方法

public Map<String, Object> loginUser(LoginVo loginVo) {
  …………
    //jwt生成token字符串
    String token = JwtHelper.createToken(userInfo.getId(), name);
    map.put("token",token);
    return map;
}

修改实现类代码:
在这里插入图片描述

启动项目:
在这里插入图片描述

测试;
在这里插入图片描述

测试成功:
在这里插入图片描述

6、阿里云短信

6.1阿里云短信介绍

后面的注意了,可以申请短信服务,把是否涉及第三方权益选否,这样就可以个人注册,记得申请说明写不涉及商业用途

在这里插入图片描述

在这里插入图片描述

阿里腾讯都不行,建议荣联云

在这里插入图片描述
6.1.1开通阿里云短信服务

6.1.2添加签名管理与模板管理

在这里插入图片描述

注:审批通过后方可使用

注意:我们需要的三个参数:AccessKey,签名名称,模板code
不需要审核,直接使用测试的签名名称,模板code即可

①:签名名称,模板code获取方法:
阿里云官网->短线服务->免费开通->快速学习->添加测试手机号->找到测试专用签名模版即可得到签名名称,模板code数据
在这里插入图片描述

②:AccessKey获取方式:
6.1.3获取用户AccessKey

在这里插入图片描述

6.2搭建service-msm模块

6.2.1 在service父模块下搭建service-msm模块
搭建过程参考service-hosp模块
6.2.2修改配置

1、修改pom.xml

<dependencies>
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
    </dependency>
</dependencies>

2、添加配置文件application.properties

# 服务端口
server.port=8204
# 服务名
spring.application.name=service-msm

#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

#短信的验证码要放到redis中的,设置过期时间,所以这里要使用redis
spring.redis.host=192.168.44.165
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0

# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

#阿里云的那个    AccessKey ID:LTAI5tNguXrGUqFr623V2YxQ
#和AccessKey Secret:isMxPuBM6K9nOYZJVuM1VJJhYUNekA
aliyun.sms.regionId=default
aliyun.sms.accessKeyId=LT6I0Y5633pX89qC
aliyun.sms.secret=jX8D04Dm12I3gGKj345FYSzu0fq8mT

6.2.3 启动类
包路径:com.fan.yygh.msm

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源自动配置
@EnableDiscoveryClient
@ComponentScan(basePackages = {"com.fan"})  //这个以后都加上,防止出现bug
public class ServiceMsmApplication {
   public static void main(String[] args) {
      SpringApplication.run(ServiceMsmApplication.class, args);
   }
}

6.2.4 配置网关:

#设置路由id
spring.cloud.gateway.routes[3].id=service-msm
#设置路由的uri
spring.cloud.gateway.routes[3].uri=lb://service-msm
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[3].predicates= Path=/*/msm/**

6.3封装注册短信验证码接口

6.3.1 添加配置类
util包下:

package com.fan.yygh.msm.util;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class ConstantPropertiesUtils implements InitializingBean {

    @Value("${aliyun.sms.regionId}")
    private String regionId;

    @Value("${aliyun.sms.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.sms.secret}")
    private String secret;

    public static String REGION_Id;
    public static String ACCESS_KEY_ID;
    public static String SECRECT;

    @Override
    public void afterPropertiesSet() throws Exception {
        REGION_Id=regionId;
        ACCESS_KEY_ID=accessKeyId;
        SECRECT=secret;
    }
}

封装controller接口

创建好项目包路径和基本的类和接口:
在这里插入图片描述

需要的工具类RandomUtil :

public class RandomUtil {

    private static final Random random = new Random();

    private static final DecimalFormat fourdf = new DecimalFormat("0000");

    private static final DecimalFormat sixdf = new DecimalFormat("000000");

    public static String getFourBitRandom() {
        return fourdf.format(random.nextInt(10000));
    }

    public static String getSixBitRandom() {
        return sixdf.format(random.nextInt(1000000));
    }

    /**
     * 给定数组,抽取n个数据
     * @param list
     * @param n
     * @return
     */
    public static ArrayList getRandom(List list, int n) {

        Random random = new Random();

        HashMap<Object, Object> hashMap = new HashMap<Object, Object>();

// 生成随机数字并存入HashMap
        for (int i = 0; i < list.size(); i++) {

            int number = random.nextInt(100) + 1;

            hashMap.put(number, i);
        }

// 从HashMap导入数组
        Object[] robjs = hashMap.values().toArray();

        ArrayList r = new ArrayList();

// 遍历数组并打印数据
        for (int i = 0; i < n; i++) {
            r.add(list.get((int) robjs[i]));
            System.out.print(list.get((int) robjs[i]) + "\t");
        }
        System.out.print("\n");
        return r;
    }
}

controller:

package com.fan.yygh.msm.controller;

import com.fan.yygh.common.result.Result;
import com.fan.yygh.msm.service.MsmService;
import com.fan.yygh.msm.util.RandomUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/api/msm")
public class MsmApiController {
    @Resource
    private MsmService msmService;
    @Resource
    private RedisTemplate<String,String> redisTemplate;

    //发送手机验证码
    @ApiOperation("//发送手机验证码")
    @GetMapping("send/{phone}")
    public Result sendCode(@PathVariable String phone){
        //从redis获取验证码,如果获取获取到,返回ok
        // key 手机号  value 验证码
        String code = redisTemplate.opsForValue().get(phone);
        if(!StringUtils.isEmpty(code)){//redis中的code验证码不为空
            return Result.ok();
        }
        //如果从redis获取不到验证码
        //则我们自己生成新的验证码,6位的
        code = RandomUtil.getSixBitRandom();
        //调用service方法,通过整合短信服务进行发送
        //我们这里需要来年各个参数,一个是手机号,一个是我们生成的验证码
        boolean isSend =  msmService.send(phone,code);
        //生成的验证码方法redis中,并设置验证码的有效时间
        if(isSend){//如果发送成功
            //redis的set(K var1, V var2, long var3, TimeUnit var5)
            redisTemplate.opsForValue()
                    .set(phone,code,2L, TimeUnit.MINUTES);
            return Result.ok();
        }else{
            return Result.fail().message("发送短信失败!!!");
        }
    }
}

send方法的实现:

package com.fan.yygh.msm.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.fan.yygh.msm.service.MsmService;
import com.fan.yygh.msm.util.ConstantPropertiesUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;

@Service
public class MsmServiceImpl implements MsmService {

    //调用service方法,通过整合短信服务进行发送
    @Override
    public boolean send(String phone, String code) {
        //判断手机号是否为空
        if(StringUtils.isEmpty(phone)){
            return false;
        }
        //整合阿里云短信服务
        //设置相关参数
        DefaultProfile profile = DefaultProfile.
                getProfile(ConstantPropertiesUtils.REGION_Id,
                        ConstantPropertiesUtils.ACCESS_KEY_ID,
                        ConstantPropertiesUtils.SECRECT);
        IAcsClient client = new DefaultAcsClient(profile);
        //创建一个CommonRequest  request
        CommonRequest request = new CommonRequest();
        //request.setProtocol(ProtocolType.HTTPS);
        request.setMethod(MethodType.POST);
        request.setDomain("dysmsapi.aliyuncs.com");
        request.setVersion("2017-05-25");
        request.setAction("SendSms");

        //向request的放入手机号
        request.putQueryParameter("PhoneNumbers",phone);
        //向request的放入签名名称
        request.putQueryParameter("SignName","阿里云短信测试");
        //向request的放入模板code,前边阿里云网页的那个数据
        request.putQueryParameter("TemplateCode","SMS_154950909");
        //验证码  使用json格式   {"code":"123456"}
        HashMap<String, Object> param = new HashMap<>();
        param.put("code",code);
        //向request的放入模板参数,将验证码参数转成json,使用map进行转换
        request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));

        //调用方法进行短信发送
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            return response.getHttpResponse().isSuccess();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }

        return false;
    }
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

启动测试:swagger:8204端口

在这里插入图片描述

我自己测试的:

{“Message”:“账户余额不足”,“RequestId”:“27360B99-4296-5055-8594-7F00D0489700”,“Code”:“isv.AMOUNT_NOT_ENOUGH”}

换到user登录模块:找到实现类,修改
在这里插入图片描述

swagger测试:我用测试短信,提示我余额不足,我冲了1块钱才发成功短信的验证码;

在这里插入图片描述

在这里插入图片描述

7、登录前端

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文件
在这里插入图片描述

说明:登录成功用户信息记录cookie

7.4 头部显示登录状态

7.4.2 登录页面控制

  created() {
    this.showInfo()
  },
    showInfo() {
      let token = cookie.get('token')
      if (token) {
        this.name = cookie.get('name')
      }
    },

7.4.1 获取登录信息

在这里插入图片描述

在这里插入图片描述

说明:实名认证“command”的值为下拉列表的访问路径,即:实名认证的访问路径,后续会有对应的页面,目前我们将它处理好,方便后续使用
添加下拉列表事件处理:

问题一:
增加的东西:一打开页面css 乱的(即页面不出来,出来一些html文字),在 el-dialog标签中 加个v-if=“dialogUserFormVisible”

问题二:

后台数据包redis连接不上问题的:
需要在service_user的配置文件增加redis的配置:

#redis配置
spring.cache.type=redis
spring.redis.database=0
spring.redis.port=6379
spring.redis.host=192.168.211.xxx
spring.redis.password=
spring.redis.timeout=1800000

问题三:
页面不报错登录不上去的:检查我们的

  1. UserInfoApiController类接口和前端接口的路径是否一样。
  2. 仔细检查我们是否返回了结果:
  3. 在这里插入图片描述

在这里插入图片描述

注意需要启动的服务:
在这里插入图片描述

在这里插入图片描述

最后成功:

在这里插入图片描述

8、登录全局事件

目前登录层在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,点击科室测试

三、用户认证与网关整合

思路:
1.所有请求都会经过服务网关,服务网关对外暴露服务,在网关进行统一用户认证;
2.既然要在网关进行用户认证,网关得知道对哪些url进行认证,所以我们得对ur制定规则
3.Api接口异步请求的,我们采取url规则匹配,如:/api//auth/,如凡是满足该规则的都必须用户认证

1、调整server-gateway模块

1.1在服务网关添加fillter
在这里插入图片描述

找到工具类:
在这里插入图片描述

在这里插入图片描述

1.2在服务网关中判断用户登录状态

在网关中如何获取用户信息:
1,我们统一从header头信息中获取
如何判断用户信息合法:
登录时我们返回用户token,在服务网关中获取到token后,我在到redis中去查看用户id,如何用户id存在,则token合法,否则不合法
1.3 取用户信息

/**
 * 获取当前登录用户id
 * @param request
 * @return
 */
private Long getUserId(ServerHttpRequest request) {
    String token = "";
    List<String> tokenList = request.getHeaders().get("token");
    if(null  != tokenList) {
        token = tokenList.get(0);
    }
    if(!StringUtils.isEmpty(token)) {
        return JwtHelper.getUserId(token);
    }
    return null;
}

2、调整前端yygh-site

请求服务器端接口时我们默认带上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
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值