前言

nestjs官方文档是英文,太难搞了,摸索了两天 ,把经验记下来。 以后备用

目录结构

|--src  //项目根目录
|--modules // 模块 比如用户模块,商品模块
|--app //入口模块
|--utils //一些工具类,比如生成token
|--decorator //自定义注解
|--guard // 自定义守卫
|--constants.ts //常量
|--main.ts //启动入口

登录

小程序前端传入js_code,后端拿这个请求微信服务端,获得用户信息(openid, session_key)

小程序登录页面的js

async onLogin() {
const { code } = await wx.login();
const url = 'http://localhost:3000/login';
const {data} = await request({method:"POST", url, data:{code} });
// 登录成功之后 将token存入全局 并重定向到首页
wx.setStorageSync('token', data.token);
wx.redirectTo({url: '/pages/index/index'})
}

后端controller 登录成功之后 将token返回给前端 让其存储起来 以后每次请求都要携带 作为身份识别

  @Post('login')
async onLogin(@Body('code') js_code: string): Promise<any> {
const token = await this.utils.genToken(js_code);
return { token };
}

后端 utils.ts 里genToken代码

import { JwtService } from '@nestjs/jwt';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom, map } from 'rxjs';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; @Injectable()
export default class Utils {
constructor(
private readonly httpService: HttpService,
private readonly jwtService: JwtService,
) {}
async genToken(js_code: string) {
// openid是用户在同一个小程序下的唯一表示,
// 即同一个用户在不同的小程序下的openid是不同的
// 所以当你的appid变化之后,用户的openid就会发生变化,只变AppSecret时 openid是不会变的。
const params: any = {
appid: 'xxxxxx', // 管理员在微信公众平台获取
secret: 'xxxxxx', // 管理员在微信公众平台获取
grant_type: 'authorization_code', // 写死
js_code,
};
// 请求微信服务端接口 返回session_key和openid
const res = await firstValueFrom(
this.httpService
.get('https://api.weixin.qq.com/sns/jscode2session', { params })
.pipe(map((response) => response.data)),
); const { openid, session_key, errcode } = res; // 如果微信服务端抛出错误,则将错误直接返回给前端
if (errcode) {
// https://betheme.net/news/txtlist_i90049v.html?action=onClick
throw new HttpException({ ...res }, HttpStatus.INTERNAL_SERVER_ERROR);
} else {
// 根据session_key和openid 组合成一个用户登录唯一标识token 并维护其生命周期(比如会话变更 就需要重新让其登录)
// 之后的小程序端的每一个请求都需要携带此token 让我鉴权
return this.jwtService.sign({ openid, session_key });
}
}
}

获取用户信息

接上步, 如果小程序登录成功 应该跳转到首页。 首页一般都会调用一些接口 比如获取用户信息啥的 这里举例获得用户的openid

后端controller

  @Post('userinfo')
userInfo(@AuthUser() user) {
console.log(user);
return { data: {} };
}

@AuthUser 是自定义的一个注解,用来获取请求参数中的user的,在decorator/index.ts

当然你也可以不用注解 而通过接受@Request 里获取,只是麻烦些而已。

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const AuthUser = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
},
);

为啥请求参数里有个user呢 这是因为 我将user注入到全局所有的request里了 通过守卫guard/auth.guard.ts

接下来讲讲这个守卫是干什么。

守卫,相当于拦截器,比拦截器写起来体验更好。

用来鉴权的,定义那些接口需要token 哪些不需要token 一般处理登录登出接口 其它都需要

并在这里边 将token解码 将解码后的内容塞入request 以便后续的controller 们使用

import {
Injectable,
Inject,
CanActivate,
HttpException,
HttpStatus,
ExecutionContext,
UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt'; @Injectable()
export class AuthGuard implements CanActivate {
@Inject()
private readonly jwtService: JwtService; // context 请求的(Response/Request)的引用
async canActivate(context: ExecutionContext): Promise<boolean> {
// console.log('进入全局权限守卫...');
// 获取请求对象
const request = context.switchToHttp().getRequest();
// 获取请求头中的token字段
const token = context.switchToRpc().getData().headers.token;
// 如果白名单内的路由就不拦截直接通过
if (this.hasUrl(this.urlList, request.url)) {
return true;
}
// 验证token的合理性以及根据token做出相应的操作
if (token) {
try {
// 这里可以添加验证逻辑
const payload = this.jwtService.verify(token);
request.user = payload; // 注入到请求中 这样每个控制器直接拿到用户信息 不用每个都需要去解码了
return true;
} catch (e) {
throw new HttpException(
'没有授权访问,请先登录',
HttpStatus.UNAUTHORIZED,
);
}
} else {
throw new HttpException('没有授权访问,请先登录', HttpStatus.UNAUTHORIZED);
}
} // 白名单数组
private urlList: string[] = ['/login']; // 验证该次请求是否为白名单内的路由
private hasUrl(urlList: string[], url: string): boolean {
let flag: boolean = false;
if (urlList.indexOf(url) >= 0) {
flag = true;
}
return flag;
}
}

最后注意语法

app.module.ts 里需要提前注入这些依赖 方可在上遍中 使用一些服务和工具

import { HttpModule } from '@nestjs/axios';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { JwtModule } from '@nestjs/jwt';
import Utils from '../../utils';
import { APP_GUARD } from '@nestjs/core';
import { AuthGuard } from 'src/guard/auth.guard'; @Module({
imports: [
HttpModule,
JwtModule.register({ // 注入jwt模块
secret: 'dsh',
signOptions: { expiresIn: '60s' },
}),
],
controllers: [AppController],
providers: [
AppService,
Utils,
{ // 注将自定义守卫入全局
provide: APP_GUARD,
useClass: AuthGuard,
},
],
})
export class AppModule {}

nestjs微信小程序登录授权的更多相关文章

  1. uni-app微信小程序登录授权

    微信小程序授权是非常简单和常用的功能,但为了方便,还是在此记录一下要点: 首先是需要用到一个授权按钮来触发获取用户信息授权: 关键在于 open-type 为 getUserInfo , 然后有个@g ...

  2. 关于微信小程序登录授权

    小程序的API接口文档写的很清晰,现在理一遍思路. 前端通过wx.login()获取code ,把code发给后台,后台返回openid,再获取用户的授权信息(这里先判断是否授权,授权过的就直接进入小 ...

  3. 微信小程序登录授权并获取手机号

    一.请求发送 携带 code 到后台换取 openid var that = this; wx.login({ success(res) { console.log(res); var code = ...

  4. spring mvc+redis实现微信小程序登录

    本文将详细的介绍微信小程序的登录流程以及在ssm框架下如何实现小程序用户登录 登录流程概要 主要的登录流程可以参考官方提供的一张流程图: 1.微信前台页面: 在微信版本更新之后,提高了安全机制,我们需 ...

  5. 基于Shiro,JWT实现微信小程序登录完整例子

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html ...

  6. 微信小程序登录JAVA后台

    代码地址如下:http://www.demodashi.com/demo/12736.html 登录流程时序登录流程时序 具体的登录说明查看 小程序官方API 项目的结构图: springboot项目 ...

  7. 微信小程序登录对接Django后端实现JWT方式验证登录

    先上效果图 点击授权按钮后可以显示部分资料和头像,点击修改资料可以修改部分资料. 流程 1.使用微信小程序登录和获取用户信息Api接口 2.把Api获取的用户资料和code发送给django后端 3. ...

  8. 全栈项目|小书架|微信小程序-登录及token鉴权

    小程序登录 之前也写过微信小程序登录的相关文章: 微信小程序~新版授权用户登录例子 微信小程序-携带Token无感知登录的网络请求方案 微信小程序开通云开发并利用云函数获取Openid 也可以通过官方 ...

  9. Flask与微信小程序登录(后端)

    开发微信小程序时,接入小程序的授权登录可以快速实现用户注册登录的步骤,是快速建立用户体系的重要一步.这篇文章将介绍 python + flask + 微信小程序实现用户快速注册登录方案(本文主要进行后 ...

  10. Spring Security 整合 微信小程序登录的思路探讨

    1. 前言 原本打算把Spring Security中OAuth 2.0的机制讲完后,用小程序登录来实战一下,发现小程序登录流程和Spring Security中OAuth 2.0登录的流程有点不一样 ...

随机推荐

  1. ESP32系列,IDF官方实例——外设:通用GPIO

    示例位于 \examples\peripherals\gpio\generic_gpio 文件夹内 GPIO示例逻辑简单,直接看代码理解. /* GPIO示例 此示例代码位于公共域(或CC0许可,由您 ...

  2. pytorch 实战教程之 SPP(SPPNet---Spatial Pyramid Pooling)空间金字塔池化网络代码实现 和 SPPF (Spatial Pyramid Pooling Fast)详解​​

    原文作者:aircraft 原文链接:pytorch 实战教程之 SPP(SPPNet---Spatial Pyramid Pooling)空间金字塔池化网络代码实现 和 SPPF (Spatial ...

  3. 网鼎杯-nmap

    Web 0x01 nmap 查看源码提示: 研究了半天分隔符绕过,后来放弃了,根据题目提示(127.0.01,不用扫外网),尝试扫描/flag并尝试将其输出到1.txt中 -iL /flag -oN ...

  4. 最小生成树 & 严格次小生成树

    最小生成树 何为最小生成树? 有一类问题:给定一张图,可以删除若干条边,在不改变连通性(一般是全联通)的情况下,权值和最小的方案是什么?没错,这就是最小生成树问题(MST问题).那么基本性质其实连聪明 ...

  5. 信息资源管理综合题之“某国企投资IT应用人员减少但生成率没有实质性变化的IT黑洞问题”

    一.某大型国企在IT应用上投资了2000万美元,虽然蓝领工人数量大幅减少,但实际生产率并未有实质性变化 1.企业在IT应用上的巨额投资并未达到预期目标的这种现象被称为什么? 2.产生这现象的原因有哪些 ...

  6. LR梯度下降法MSE演练

    同步进行一波网上代码搬砖, 先来个入门的线性回归模型训练, 基于梯度下降法来, 优化用 MSE 来做. 理论部分就不讲了, 网上一大堆, 我自己也是理解好多年了, 什么 偏导数, 梯度(多远函数一阶偏 ...

  7. windows系统安装redis教程

    redis官方特地开发了个windows版本,不过不更新维护.适合在本地测试项目 下载地址:https://github.com/microsoftarchive/redis/releases/tag ...

  8. MySQL修改表和字段的字符集和排序规则

    摘要:通过设置表的字符集和排序规则,解决MySQL查询时不区分字母大小写.插入时不支持特殊字符的问题.   关于MySQL查询时不区分字母大小写.插入时不支持特殊字符的问题,只有修改表的字符集和排序规 ...

  9. REVM移植小记

      之前做过的一些部署移植的工作,基本都是用C++语言写的,在后来我学了一些Rust,并且慢慢熟悉了Rust的工具链,最近也在尝试部署一些Rust的开源项目到OpenEuler RISC-V操作系统上 ...

  10. TUF系统概述

    TUF基本介绍 TUF 是一个为软件更新系统设计的安全框架,最初由纽约大学的 Secure Systems Lab 提出.它的目标是解决传统软件更新过程中的各种安全问题(如中间人攻击.回滚攻击.密钥泄 ...