/**PageBeginHtml Block Begin **/ /***自定义返回顶部小火箭***/ /*生成博客目录的JS 开始*/ /*生成博客目录的JS 结束*/

一种移动端的token设计方案(适合app+h5)

一种移动端的token设计方案(适合app+h5)

需求分析:

1、用户中台赋能各大应用,统一接管登录注册,验证用户账号密码。原有的应用用户体系内部逻辑不变。

2、兼容app端,H5端及app混合H5端,无缝连接。

 

设计思路:

用户中台只负责认证账号密码,并下发ticket凭证。

应用收到ticket后,自主维护本应用的验证体系gw-token以及有效登录时长,当gw-token失效时,可重新使用ticket进行静默验证登录。

好处:

1、用户中台没有gw-token维护的压力,只做关键验证,提高可用性和效率。

2、应用维护gw-token,相对独立,灵活性更高。

3、使用ticket和token机制,挂平台,在app和h5之间无缝传递和对接。

 

 

 

 

 



  • 移动端与服务器端之间的 token 怎么设计?

作者:做个前端

链接:https://www.jianshu.com/p/e07f51c5c8bd

网上关于移动客户端与服务器数据传输之间的 token 的细节使用好像都没有详细的说明,基本都是一笔带过。对于简简单单的加入一个固定的参数 token,其实是很容易被抓包的。

介绍

token 是登录之后服务器返回的一段加密字符串(加密算法自己与后台商量如何加解密),存储到本地。在客户端请求服务端数据的时候可以带上(放在请求头headers,参数都行),更新 token 的方法自己与后台商量,以下只是思路。

下面说一下我自己的方案:

image

启动页判断本地是否存在 token

为啥在启动页更新 token 呢?是因为启动页在第一个页面,一般都会有几秒的等待时间,是不做网络请求操作的,而且页面使用率高。这样随机更新可以说安全性高。

a)本地存在 token

1)客户端使用旧 token 请求更新 token
2)服务器判断 redis 是否存在 token
3)存在则生成新的token 存储在 redis 中,删除旧的 token
4)不存在则判断该用户是否存在另一个与之不相等的 token
5)存在与之不相等的 token则说明该用户账号在其他设备登录
6)不存在~则说明过期被删除或者在其他设备登录之后退出登录被删除(设置token过期时间为30天)

b)本地不存在 token

1)有三种情况,一种重来没登录过,一种是在新设备登录,一种是登录后退出用户

退出用户

网络请求删除 redis 中的token,并删除本地的 token





手机app 与后台 token 生成及验证 java 代码实例 登录生成token

转载

小鱼儿2024-07-01 05:45:57

文章标签python后端数据库webtornado文章分类Java后端开发阅读数69

1.为什么需要登录认证

换句话来说,为什么需要session、cookie和token
这个认证信息需要的原因,就是比如说我们今天使用淘宝点击添加购物车,然后就需要一个请求,但是发送这个请求之前,需要验证是哪个用户所登录,所以就需要一个类似通行码的东西去标识已登录。所以就存在了这些东西是吧?

2.session、cookie和token的区别

这个session的话,首先出现了他,他存储再服务端,但是服务器压力就很大,如果出现了损坏,大家都得重新登录,所以出现了cookie。cookie是存储在客户端的,但是如果web服务器做了负载均衡,下一个操作请求到了另一个服务器session就会丢失。就是无法跨设备免密登录。然后就出现了token,token是随着登录成功一起生成保存在客户端,客户端每次访问的话都是携带者token去访问服务端,所以就更加好

3.实操

image

当我们登录成功以后,并没有一个相应的标识,做出特殊的处理。这里,我们登录成功以后,就需要一个通行证的东西,去标识我们已经登录。这里可以是session、token标识。本次,我们将使用jwt(JSON WEB TOKEN)

jwt是用于生成token

jwt官网:jwt.io

jwt使用方法: github

4.用户登录_生成Token并响应——使用jwt

2.1下载jwt

pip install pyjwt

2.2 代码展示

# forum/handler/UserHandler.py
from forum.wtforms import UserForm,LoginUserForm
from forum import manager
from forum.models import UserModel
from uuid import uuid4
from forum.handler.BaseHandler import BaseHandler
from forum.utils.email_utils import send_mail
from forum.utils.redis_utils import *
from random import randint
import jwt
from config import secret,email
# 登录接口
class LoginHandler(BaseHandler):
    async def post(self):
        # 记录登录信息
        print("1234")
        rs_data = {}
        # 获取表单数据
        user_form = LoginUserForm(self.request.arguments)
        # 验证是否符合form表单输入的规则
        if user_form.validate():
            try:
                # 数据库中获取
                user = await manager.get(UserModel, email=user_form.email.data, password=user_form.password.data)
                # 获取到了,登录成功
                print(user_form.email.data)
                print(user_form.password.data)
                rs_data['code'] =200
                rs_data['msg'] = '登录成功!!!'
                payload = {
                    'email': user_form.email.data
                }
                # 生成一个用户信息(加密)token,返回给前端,下一次访问时,携带用户信息回来即可
                token = jwt.encode(payload, secret, algorithm='HS256')# 参数含义:加密谁,加密的密码(盐)、加密的算法
                rs_data['token'] = token
            except Exception as e:
                # 获取不到,登录失败
                rs_data['code'] = 401
                rs_data['msg'] = '用户名或密码错误'
        else:
            rs_data['code'] = 401
            rs_data['msg'] = '用户名不符合规范'
            for f in user_form.errors:
                print(user_form.errors)
                rs_data[f] = user_form.errors[f][0]
        self.finish(rs_data)

2.3 登录完成效果展示

image


5.用户登录_token获取用户信息

5.1概述

当我们登录完成以后,前端并没有展示出登录成功的状态。这里我们需要一个接口,获取用户登录成功的信息,获取他的登录通行证token。从token中解析是否存在数据email,如果存在则登录成功。(token是随着登录时一起产生在服务端的,存放在请求头中)

5.2代码展示
5.2.1转换用户信息
# forum/models.py
# 用于创建数据表模型
from peewee import *
from forum import database
from datetime import datetime
# 创建基类:减少重复代码
class BaseModel(Model):
    create_time = DateTimeField(default = datetime.now)
    # 创建函数,用于返回用户的信息位字典形式
    def to_json(self) -> dict:
        r = {}
        for k in self.__data__.keys():
            # 判断数据是否是create_time(时间不是字符串)
            if k == 'create_time':
                r[k] = str(getattr(self,k))
            else:
                r[k] = getattr(self,k)
        return r
5.2.2 token获取用户信息接口实现——免密登录
# forum/handler/UserHandler.py
from forum.wtforms import UserForm,LoginUserForm
from forum import manager
from forum.models import UserModel
from uuid import uuid4
from forum.handler.BaseHandler import BaseHandler
from forum.utils.email_utils import send_mail
from forum.utils.redis_utils import *
from random import randint
import jwt
from config import secret,email

# token获取用户信息接口实现——免密登录
class GetUserHandler(BaseHandler):
    async def get(self):
        rs_data = {}
        # 获取token
        token = self.request.headers.get('token')
        # 从token值解析出email
        payload = jwt.decode(token, secret, algorithms=['HS256'])
        if payload:
            # 通过email查询数据
            email = payload.get('email')
            user = await manager.get(UserModel, email=email)
            # 判断是否存在这个用户
            if user:
                # 有数据,将用户信息返回给前端
                rs_data['code'] = 200
                rs_data['msg'] = '获取用户成功!!!'
                rs_data['user'] = user.to_json()
                # 没有数据,没有登录
            else:
                rs_data['code'] = 500
                rs_data['msg'] = 'toekn错误!!!'
        else:
            rs_data['code'] = 500
            rs_data['msg'] = '请登录后再操作!!!'
        self.finish(rs_data)

5.3 效果展示

image

6.装饰器验证是否登录

装饰器

# forum/wtforms.py
# 完整注册(给t_user表)增加数据之前的数据验证
from wtforms_tornado import Form
from wtforms.fields import StringField
from wtforms.fields.simple import HiddenField
from wtforms.validators import DataRequired, Length

# 对t_user的数据验证
class UserForm(Form):
    id = HiddenField()
    email = StringField('账号', validators=[DataRequired(message='请填写合法的邮箱地址'),Length(min=5, max=20, message='请输入5-20长度的邮箱')])
    nick_name = StringField('昵称', validators=[Length(min=2, max=10, message='请输入2-10长度的昵称')])
    password = StringField('密码', validators=[Length(min=2, message='请输入2以上长度的密码')])
    signature = StringField('签名')
    pic = StringField('头像')

# 对登录的数据验证
class LoginUserForm(Form):
    id = HiddenField()
    email = StringField('账号', validators=[DataRequired(message='请填写合法的邮箱地址'),Length(min=5, max=20, message='请输入5-20长度的邮箱')])
    nick_name = StringField('昵称')
    password = StringField('密码', validators=[Length(min=2, message='请输入2以上长度的密码')])
    signature = StringField('签名')
    pic = StringField('头像')

优化免密登录

# forum/handler/UserHandler.py
from uuid import uuid4
from random import randint

import jwt

from forum.wtforms import UserForm,LoginUserForm
from forum import manager
from forum.models import UserModel
from forum.handler.BaseHandler import BaseHandler
from forum.utils.email_utils import send_mail
from forum.utils.redis_utils import *
from config import secret,email
from forum.decorators import login_required_async

# 调用wtforms做添加用户数据之前的数据表单验证
class AddUserHandler(BaseHandler):
    async def post(self):
        # 创建应该响应对象
        rs_data = {}
        # 接受请求的参数并封装到Form对象中
        user_form = UserForm(self.request.arguments)
        # 前端传递的验证码
        code = self.get_body_argument('code')
        # 后端的正确的验证码
        db_code = get_code(user_form.email.data)
        if code == db_code:
            if user_form.validate():
                # 从表单中获取email信息
                email = user_form.email.data
                try:
                    # 异步查询数据表信息
                    exist_user = await manager.get(UserModel,email = email)
                    if exist_user:
                        # 存在此用户,验证失败
                        rs_data['code'] = 500
                        rs_data['msg'] = '用户名已存在'
                except Exception as e:
                    # 验证成功
                    # 异步保存数据到数据库中
                    user_form.id.data = uuid4()
                    await manager.create(UserModel,**user_form.data)
                    rs_data['code'] = 200
                    rs_data['msg'] = '注册成功'
            else:
                # 验证失败
                rs_data['code'] = 500
                rs_data['msg'] = '注册失败'
                # 将验证失败的具体原因返回给rs_data,提示信息
                for f in user_form.errors:
                    rs_data[f] = user_form.errors[f][0]
        else:
            # 验证失败
                rs_data['code'] = 500
                rs_data['msg'] = '验证码错误'
        self.finish(rs_data)


# 发送邮件
class SendEmailHandler(BaseHandler):
    # 用于给定4位随机验证码
    def generate_code(self) -> int:
        return randint(1000,9999)
    # 发送邮件的接口
    def post(self):
        user_email = self.get_body_argument('email') # 获取前端form输入框中输入的邮箱
        code = self.generate_code()
        msg = f'您好,您正在使用{user_email}注册<CMS论坛项目>用户注册账号,您的验证码位{code},如果不是本人操作,请忽略'
        send_mail(email.get('uname'),email.get('pwd'),user_email,'<CMS论坛项目>用户注册',msg)
        save_code(user_email,code)

# 登录接口
class LoginHandler(BaseHandler):
    async def post(self):
        # 记录登录信息
        print("1234")
        rs_data = {}
        # 获取表单数据
        user_form = LoginUserForm(self.request.arguments)
        # 验证是否符合form表单输入的规则
        if user_form.validate():
            try:
                # 数据库中获取
                user = await manager.get(UserModel, email=user_form.email.data, password=user_form.password.data)
                # 获取到了,登录成功
                print(user_form.email.data)
                print(user_form.password.data)
                rs_data['code'] =200
                rs_data['msg'] = '登录成功!!!'
                payload = {
                    'email': user_form.email.data
                }
                # 生成一个用户信息(加密)token,返回给前端,下一次访问时,携带用户信息回来即可
                token = jwt.encode(payload, secret, algorithm='HS256')# 参数含义:加密谁,加密的密码(盐)、加密的算法
                rs_data['token'] = token
            except Exception as e:
                # 获取不到,登录失败
                rs_data['code'] = 401
                rs_data['msg'] = '用户名或密码错误'
        else:
            rs_data['code'] = 401
            rs_data['msg'] = '用户名不符合规范'
            for f in user_form.errors:
                print(user_form.errors)
                rs_data[f] = user_form.errors[f][0]
        self.finish(rs_data)

# token获取用户信息接口实现——免密登录
class GetUserHandler(BaseHandler):
    @login_required_async
    async def get(self):
        rs_data = {}
        id = self._user_id
        try:
            user = await manager.get(UserModel,id=id)
            # 判断是否存在这个用户
            if user:
                # 有数据,将用户信息返回给前端
                rs_data['code'] = 200
                rs_data['msg'] = '获取用户成功!!!'
                rs_data['user'] = user.to_json()
        except Exception as e:
            rs_data['code'] = 500
            rs_data['msg'] = '请登录后再操作!!!'
        self.finish(rs_data)




token小程序令牌

一叶知秋2024-08-16 15:58:47JavaScript37

深入解析微信小程序Token令牌的使用与实现

随着微信小程序的普及,越来越多的开发者开始关注小程序的安全性和性能优化。Token令牌作为一种常见的身份验证机制,被广泛应用于小程序中。本文将深入解析Token令牌在微信小程序中的应用,包括生成、校验以及应用场景。

token小程序令牌

一、什么是Token令牌?

Token令牌是一种用于身份验证的字符串,它包含了用户的身份信息、权限信息以及过期时间等。在微信小程序中,Token令牌主要用于以下场景:

  1. 用户登录:用户在登录过程中,后端服务器会生成一个Token令牌,并将其发送给小程序端。小程序端将Token存储在本地,后续访问接口时携带Token进行验证。

  2. 权限控制:Token令牌中包含了用户的权限信息,后端服务器可以根据Token中的权限信息判断用户是否有权限访问某个接口。

  3. 性能优化:使用Token令牌可以减少数据库查询次数,提高接口响应速度。

二、微信小程序Token令牌的实现

  1. 生成Token令牌

(1)前端提交code码:用户在小程序登录时,前端会向微信服务器发送请求,获取code码。

(2)后端获取openid:后端服务器使用code码调用微信接口,获取用户的openid。

(3)生成Token:后端服务器使用jjwt库生成一个包含openid和过期时间的JWT(JSON Web Tokens)令牌。

以下是一个使用jjwt库生成Token的Java代码示例:


  • import io.jsonwebtoken.Jwts;
  • import io.jsonwebtoken.SignatureAlgorithm;
  • import java.util.Date;
  • public class JwtUtil {
  • public static String createToken(String openid) {
  • long nowMillis = System.currentTimeMillis();
  • Date now = new Date(nowMillis);
  • long expMillis = nowMillis + 3600 * 1000; // 过期时间设置为1小时
  • Date exp = new Date(expMillis);
  • return Jwts.builder()
  • .setSubject(openid)
  • .setIssuedAt(now)
  • .setExpiration(exp)
  • .signWith(SignatureAlgorithm.HS512, "your_secret_key")
  • .compact();
  • }
  • }
  1. 校验Token令牌

(1)前端携带Token:用户访问需要权限控制的接口时,将Token作为请求头传递给后端服务器。

(2)后端解析Token:后端服务器使用jjwt库解析Token,获取其中的openid和过期时间。

(3)验证Token:后端服务器验证Token的有效性,如果Token已过期或签名不正确,则拒绝请求。

以下是一个使用jjwt库解析Token的Java代码示例:


  • import io.jsonwebtoken.Claims;
  • import io.jsonwebtoken.Jwts;
  • import io.jsonwebtoken.SignatureAlgorithm;
  • import java.util.Date;
  • public class JwtUtil {
  • public static Claims parseToken(String token) {
  • return Jwts.parser()
  • .setSigningKey("your_secret_key")
  • .parseClaimsJws(token)
  • .getBody();
  • }
  • }

三、Token令牌的应用场景

  1. 登录状态保持:使用Token令牌可以方便地在用户登录后保持登录状态,无需重复输入用户名和密码。

  2. 接口权限控制:通过Token令牌中的权限信息,后端服务器可以实现对接口的权限控制,防止非法访问。

  3. 优化性能:使用Token令牌可以减少数据库查询次数,提高接口响应速度,从而优化性能。

Token令牌是一种高效、安全的身份验证机制,在微信小程序中具有广泛的应用。本文详细介绍了Token令牌在微信小程序中的生成、校验和应用场景,希望对开发者有所帮助。



posted @ 2024-10-11 09:09  一品堂.技术学习笔记  阅读(37)  评论(0编辑  收藏  举报