在线教育-谷粒学院学习笔记(十一)

1 内容介绍

  • 登录前端整合

  • 微信扫码登录

    • OAuth2

    • 微信登录

2 登录前端整合

1 api创建login.js文件,定义接口地址

// 登录
submitLogin(userInfo) {
  return request({
    url: `/educenter/member/login`,
    methods: 'post',
    data: userInfo
  })
},
// 根据token获取用户信息
getLoginUserInfo() {
  return request({
    url: `/educenter/member/getMemberInfo`,
    methods: 'get'
  })
}

2 登录页面调用

下载插件:npm install js-cookie

登录和登录成功后首页显示数据实现过程分析

1、调用登录接口,返回token字符串

2、将token放到cookie里面

3、创建前端拦截器

判断cookie里面是否有token,如果有,把token放到header(请求头)

4、根据token调用接口,获取到用户信息,再将返回的用户信息放入cookie

5、首页从cookie中获取到用户信息并显示

// 登录
submitLogin() {
  // 1. 调用接口进行登录,返回token字符串
  loginApi.submitLoginUser(this.user)
    .then(response => {
      // 2. 把获取的token放入cookie
      // 参数:cookie名称、cookie值、作用范围
      cookie.set('guli_token', response.data.data.token, { domain: 'localhost' })
      // 3. 创建前端拦截器 utils/request
      // 4. 根据token获取用户信息
      loginApi.getLoginUserInfo()
        .then(response => {
          this.loginInfo = response.data.data.userInfo
          // 将获取到的用户信息放入cookie
          cookie.set('guli_ucenter', this.loginInfo, { domain: 'localhost' })
        })
      // 跳转页面
      window.location.href = '/'
      // this.$router.push({ path: '/' })
      // 5.页面显示 default.vue
    })
}

第3步

// http request 拦截器
service.interceptors.request.use(
  config => {
    if (cookie.get('guli_token')) {
      // 将cookie值放到header中
      config.headers['token'] = cookie.get('guli_token')
    }
    return config
  },
  err => {
    return Promise.reject(err)
  })

第5步

created() {
  this.showInfo()
},
methods: {
  // 创建方法,从cookie中获取用户信息
  showInfo() {
    const userStr = cookie.get('guli_ucenter')
    // 把字符串转为json对象
    if (userStr) {
      this.loginInfo = JSON.parse(userStr)
    }
  }
}

问题:跨域

nuxt:get不跨域,post跨域

分析参考:https://juejin.cn/post/6844903712134004743

3 OAuth2

OAuth2是针对特定问题的一种解决方案

主要可以解决两种问题:

  • 开放系统间授权

    • 方法令牌
  • 分布式访问问题(单点登录)

OAuth2解决方案:令牌机制,按照一定规则生成字符串,字符串包含用户信息

只是一个框架,用于授权代理

4 微信扫码登录

准备工作

1、注册开发者资质

不支持个人

微信id、微信密钥

2、申请网站应用名称

3 、要域名地址

1 在service-ucenter配置文件

微信id、密钥、域名地址

2 创建类读取配置文件内容

ConstantWxUtils

3 生成微信扫描二维码

直接请求微信提供的固定地址,向地址拼接参数

@Controller // 只是请求地址,不需要返回数据
@RequestMapping("/api/ucenter/wx")
@CrossOrigin
public class WxApiController {
    // 1、生成微信扫描二维码
    @GetMapping("login")
    public String getWxCode() {
        // 固定地址,在后面拼接参数
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";
        // redirect_url进行URLEncoder编码
        String redirect_url = "http://localhost:8160/api/ucenter/wx/callback";
        try {
            redirect_url = URLEncoder.encode(redirect_url, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String url = String.format(
                baseUrl,
                ConstantWxUtils.WX_OPEN_APP_ID,
                redirect_url,
                "atguigu"
        );
        // 重定向到请求的微信地址
        return "redirect:" + url;
    }
}

4 获取扫码人信息,添加到数据库

  • 扫描后,执行本地的callback方法,在callback获取两个值,state原样传递,code随机唯一的值

  • 使用code值,请求微信提供的固定地址,获取到两个值

    • access_token:访问凭证

    • openid:每个微信的唯一标识

  • 使用access_token、openid,再请求微信提供的固定地址,最终获取扫码人的信息

用到的技术点:

  • HttpClient
  • JSON转换工具:fastjson gson jackson

引入依赖

<dependencies>
    <!--httpclient-->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>
    <!--commons-io-->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
    </dependency>
    <!--gson-->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
    </dependency>
</dependencies>

扫码之后,在首页显示微信信息,比如昵称、头像

之前登录之后显示的用户信息,是首页从cookie中获取的数据

现在也可以按照这样的方式,把扫码后的信息放到cookie,再跳转到首页进行显示

但是,如果把用户信息放到cookie会出问题,因为cookie无法实现跨域访问

最终解决办法:

使用jwt,将微信信息生成一个token字符串,通过路径将token传递到首页面

@GetMapping("callback")
public String callback(String code, String state) {
    // 1. 获取code
    // 2. 利用code请求微信固定地址,得到access_token openid
    String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
            "?appid=%s" +
            "&secret=%s" +
            "&code=%s" +
            "&grant_type=authorization_code";
    // 拼接三个参数 appid secret code
    String accessTokenUrl = String.format(
            baseAccessTokenUrl,
            ConstantWxUtils.WX_OPEN_APP_ID,
            ConstantWxUtils.WX_OPEN_APP_SECRET,
            code
    );
    try {
        // 请求拼接好的地址,得到access_token openid
        // 使用HttpClient发送请求
        String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
        // 把accessTokenInfo字符串转换成map结构,根据map里面的key,获取对应的值
        // 使用json转换工具:gson
        Gson gson = new Gson();
        HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);
        String access_token = (String) mapAccessToken.get("access_token");
        String openid = (String) mapAccessToken.get("openid");

        // 将扫码人信息添加到数据库
        // 判断数据库表中是否存在相同的微信信息:根据openid
        UcenterMember member = memberService.getOpenIdMember(openid);
        if (member == null) { // member是空,表示微信没有注册,需要添加信息到数据库
            // 3. 使用access_token、openid,再请求微信提供的固定地址,最终获取扫码人的信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";
            // 拼接参数
            String userInfoUrl = String.format(
                    baseUserInfoUrl,
                    access_token,
                    openid
            );
            // 发送请求
            String userInfo = HttpClientUtils.get(userInfoUrl);
            // 获取userInfo 扫码人信息
            HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
            String nickName = (String) userInfoMap.get("nickname"); // 昵称
            String headimgurl = (String) userInfoMap.get("headimgurl"); // 头像

            member = new UcenterMember();
            member.setOpenid(openid);
            member.setNickname(nickName);
            member.setAvatar(headimgurl);
            memberService.save(member);
        }

        // 使用jwt,根据微信用户信息,生成token字符串
        String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());
        // 最后回到首页,并通过路径传递token
        return "redirect:http://localhost:3000?token=" + jwtToken;
    } catch (Exception e) {
        throw new GuliException(20001, "登录失败");
    }
}

5 在首页显示信息

  • 获取首页路径中的token字符串
  • 把获取到的token值放入cookie
    • 有前端的拦截器,判断cookie中是否有token,如果有,就会把token放入header
  • 调用后端接口,根据token值,获取用户信息,最后将获取到的用户信息放入cookie

default.vue

created() {
  // 获取路径中的token值
  this.token = this.$route.query.token
  if (this.token) { // 判断是否有token
    this.wxLogin()
  }
  this.showInfo()
},
methods: {
  // 创建方法,从cookie中获取用户信息
  showInfo() {
    const userStr = cookie.get('guli_ucenter')
    // 把字符串转为json对象
    if (userStr) {
      this.loginInfo = JSON.stringify(userStr)
    }
  },
  // 微信登录显示
  wxLogin() {
    // token --> cookie
    cookie.set('guli_token', this.token, { domain: 'localhost' })
    cookie.set('guli_ucenter', '', { domain: 'localhost' })
    // 调用接口:根据token获取用户信息
    loginApi.getLoginUserInfo()
      .then(response => {
        this.loginInfo = response.data.data.userInfo
        cookie.set('guli_ucenter', this.loginInfo, { domain: 'localhost' })
      })
  }
}

p207

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值