ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

统一身份认证服务毕设实战:基于Python与JWT的SSO单点登录实现

统一身份认证服务毕设实战:基于Python与JWT的SSO单点登录实现 1. 为什么把统一身份认证服务做成毕设1.1 一个场景说清楚它到底解决什么问题先别被统一身份认证服务这个名字吓住它背后解决的问题你几乎每天都在经历。想象你的学校或单位同时跑着好几套系统教务系统、图书借阅系统、邮箱系统、内部办公系统。正常运营模式下每个系统都各建一套账号密码于是你手机密码本里躺着五六个账号密码规则还不统一有的要求大小写字母加数字有的必须带特殊符号。你登录一次基本要把所有密码轮番试一遍。更要命的是系统之间的联动。比如你要打印一份教务处的课表先登录教务处网站下载文件再登录打印管理系统上传。两个系统彼此不认识你得重复提交两次身份信息。忘密码的时候更崩溃每个系统都要单独走一遍找回流程体验差到极点。统一身份认证就是为了解决这个账号林立、身份割裂的痛点。它的核心思路很朴素把判断用户身份这件事单独抽出来做成一个独立服务所有业务系统都通过它来确认用户是谁。用户只要在统一的认证中心登录一次再访问其他系统就不需要重复登录了。这个体验在行业里叫SSOSingle Sign-On单点登录你在很多一次登录处处可用的网站上实际体验过。把这个场景放进毕设非常合适因为需求一点都不虚每个人都能理解而且答辩评委大概率也是这套系统的日常使用者他一看就知道你做的是什么。1.2 这个题目凭什么值得写选毕设题目很多人有个误区以为功能堆得越多越好于是做一个XX管理系统把增删改查铺成十个页面。这种项目写起来快但答辩时讲不出深度因为里面只有是什么没有为什么。统一身份认证服务不一样它自带清晰的设计逻辑天然能讲出层次。第一它覆盖一条完整的技术链路。最小可用的认证服务至少包含前端登录页、后端接口、数据库设计、密码加密、Token签发与校验、跨域配置、登录日志。这一路走下来前后端交互、网络请求、数据存储这些基本功全被激活比闷头写页面扎实得多。第二它有很强的架构感。业务系统怎么接入认证中心登录成功后怎么跳转回来Token失效了怎么处理用户被强制下线怎么通知业务系统这些问题全都要设计不是CtrlC、CtrlV能糊弄过去的。论文的系统设计章节可以画架构图、时序图、数据流图篇幅和深度直接拉满。第三它的扩展性极强。同样是统一身份认证这个内核你可以用Python做也可以用Java、PHP做你可以做Web版也可以接小程序和App你甚至可以把登录日志做成数据可视化大屏或者写一个自动化的认证脚本配合爬虫做数据采集。项目标题里那一串JAVA、PHP、爬虫、APP、小程序、C#、C、python、数据可视化其实都能从这个主题延伸出去。第四它和真实生产环境是接轨的。去看看招聘市场身份认证、权限管理、单点登录这些关键词几乎出现在每一个后端岗位的需求里。毕设做了这个面试时至少有一个真实项目可以聊而且是一个能讲清原理、有技术亮点的项目。2. 核心方案选型动手前必须想清楚的几件事2.1 状态方案用Session还是Token在写第一行代码之前最该先想明白的是用户登录成功后业务系统怎么识别这个人是谁。老一套做法是Session。流程大概是用户在登录页面输入账号密码服务器验证通过后在服务器内存里创建一条会话记录生成一个Session ID通过Cookie返回给浏览器。之后浏览器每次请求都自动带上这个Cookie服务器查一下Session ID就知道用户是谁了。这套方案在早期单体应用里很流行实现也简单但它有几个对统一身份认证这种多系统场景几乎是致命的缺点。首先是服务器状态共享问题如果你部署了两台服务器用户在A服务器登录了请求被负载均衡转到B服务器B服务器内存里没有这个用户的Session就会判定未登录。解决办法是把Session集中存到Redis或数据库里做共享但这就等于又引入了外部依赖和额外的转移开销。其次是跨域问题Cookie默认受同源策略限制认证中心和业务系统大概率不在同一个域名下你得一直处理跨域、Cookie携带这些琐碎问题非常磨人。Token方案的思路完全不同。服务器验证用户密码后不发Session ID而是发出一串结构化的字符串——Token用户把Token保存在前端每次请求放到请求头里发给服务器服务器通过解密和签名校验来确认Token是否有效。服务器不存任何用户状态所以叫无状态认证。我做这个毕设时毫不犹豫选了Token方案。原因很简单认证中心和多个业务系统是一对多的关系业务系统根本不需要记住任何会话只需要会验证Token的签名就够了。打个比方就像健身房办年卡入场前台给你发一个带防伪标志的手环你进每个器械区工作人员只要看一眼手环上的标志就能放行不需要打电话回前台问这人到底办卡了没。2.2 具体落地JWT令牌的内部结构Token是个抽象概念真正落到代码里最常用的标准格式是JWTJSON Web Token也是我这个项目里的选择。JWT长什么样它是一串由两个点分隔成三段、经过Base64编码的字符串格式是头部.载荷.签名。猛一看是乱码拆开看每部分都很清晰。头部Header声明两个信息令牌类型是JWT签名算法用什么比如HS256HMAC-SHA256或者RS256RSA-SHA256。载荷Payload放的是真正的业务数据常见的有用户ID、用户名、过期时间exp、签发时间iat还可以塞自定义字段比如用户角色。签名Signature是拿前两段编码结果加一个密钥计算出来的作用就是防篡改任何人改动载荷里的用户ID签名校验立刻失败服务器直接拒绝。这里有个关键点JWT本身不依赖服务器保存状态业务系统拿到Token后只要本地验证签名有效、检查过期时间没过就能确认用户身份。这就是为什么业务系统接入认证中心时不需要在自己的数据库里同步任何用户会话数据。HS256和RS256的区别需要留意一下。HS256用同一个密钥进行签名和验签所以所有业务系统和认证中心必须共享一个密钥适合小规模、可控的场景RS256用私钥签名、公钥验证认证中心专门保管私钥负责签发业务系统只持有公钥负责验证适合更分散的架构。毕设里用HS256完全没问题但答辩时如果能提一句正式环境我更推荐RS256印象分会好不少。2.3 登录全流程一次SSO是怎么跑通的方案定了接着要设计流程。一个标准的、基于JWT的单点登录流程我习惯拆成四步去理解。第一步用户访问业务系统A。A的前端发现本地没有Token就把用户重定向到认证中心的登录页。这一步通常带一个回调地址参数告诉认证中心验完身份后把人送回哪个地址。第二步用户在认证中心输入账号密码。认证中心验证密码正确后做两件事一是在认证中心域名下种下一个已登录的标记一般是签过名的Cookie二是生成一个一次性的授权码Code然后让用户带着这个Code重定向回业务系统A的回调地址。第三步业务系统A的后端收到这个Code拿它去调用认证中心提供的换取Token接口。认证中心验证Code有效就返回正式的JWT。这里的关键设计是Code只能使用一次有效期极短防止中途被劫持复用。第四步业务系统A的前端拿到JWT之后的每次请求都带上它。当用户后来又去访问同样纳入认证体系的业务系统B时B发现没有Token也会跳转认证中心。但认证中心一看用户已经登录过了第二步种下的Cookie还在就不会再要求输密码而是直接生成Code送回业务系统BB再拿着Code换Token流程走一遍但用户无感知。这个流程里最核心的一句话是认证中心兜底。所有业务系统都不自己比对账号密码只信任认证中心的校验结果。这也正好回答了一个很多同学会问的问题为什么我不能在一台服务器上登录后另一台服务器直接用同一个Token因为Token本身就是答案你不需要跨服务器同步任何东西大家都能验同一套签发的Token。2.4 数据表设计不复杂但要想清楚我设计库表时没有铺太多表核心就四张。用户表user存账号、密码哈希值、盐值、昵称、状态正常/锁定、创建时间。密码绝对不能存明文这是我反复强调的一点后面会展开。客户端应用表app_client存每个接入方的基本信息比如应用名称、应用ID、应用密钥、回调地址白名单。这个表的意义是让认证中心知道谁有资格接入并且在换取Token时校验回调地址是否在白名单内防止别人伪造回调。授权码表auth_code在真正的生产环境里通常不落库而是放Redis并设置极短过期时间但如果你不想在毕设里引入Redis也可以暂时用数据库表实现字段就是授权码、关联用户ID、关联客户端ID、过期时间、是否已使用。它的核心约束是一次性用过即失效。登录日志表login_log记录谁在什么时间什么IP登录了这是后面做数据可视化、做安全审计的数据来源。字段建议包含用户ID、登录时间、IP地址、登录结果、失败原因。这套表结构看起来简简单单但把认证中心需要承担的责任都落实了管用户、管接入方、管临时凭证、留审计记录。3. 用Python实现认证中心的完整过程3.1 技术栈Flask PyJWT RedisPython做Web后端主流选择是Flask和Django。我选Flask核心原因是认证服务本身功能边界清晰不需要Django那一整套自带的管理后台、ORM、模板引擎Flask轻量灵活写起来更直观。尤其是毕设阶段代码量不大Flask的短小精悍能让你把注意力放在认证逻辑本身。配套组件里PyJWT是专门用来生成和校验JWT的库接口简单文档清楚省去自己实现签名算法的麻烦。Redis在这个项目里有两个用途一是存授权码设置几十秒过期天然支持过期删除二是维护Token黑名单用户登出后把Token塞进黑名单设置与Token剩余寿命一致的过期时间就能实现登出即失效。如果你本地没装RedisWindows上可以用Memurai或者干脆直接在代码里用字典加时间戳实现一个简易版但正式演示时我建议还是把Redis跑起来答辩时可以多讲一句用Redis管理短期凭证和黑名单避免频繁写数据库这也是一个加分点。3.2 用户登录接口与密码存储先看密码存储。这是整个系统安全性的地基也是最容易被人挑刺的点。正确做法是加盐哈希存储。给每个用户的密码拼上一段随机生成的盐值再用不可逆的哈希算法处理。推荐用bcrypt或者PBKDF2Python里可以直接用werkzeug.security这个工具包它内置了generate_password_hash和check_password_hash底层就是加盐哈希用起来很方便。from werkzeug.security import generate_password_hash, check_password_hash # 注册时生成哈希并存储 hashed generate_password_hash(用户输入的明文密码) # 保存 hashed 到数据库注意不要再保存明文 # 登录时比对哈希 is_ok check_password_hash(hashed, 用户再次输入的明文密码)登录接口的逻辑并不复杂整体流程是前端提交账号密码后端先查用户是否存在、状态是否正常然后用check_password_hash比对密码比对成功就把用户ID和登录时间组装进JWT生成Token返回给前端。from flask import Flask, request, jsonify import jwt import datetime app Flask(__name__) SECRET_KEY your-secret-key-change-me app.route(/api/login, methods[POST]) def login(): data request.get_json() username data.get(username) password data.get(password) # 查询用户、校验密码代码省略取到 user 对象 user find_user_by_username(username) if not user or not check_password_hash(user.password_hash, password): return jsonify({code: 401, msg: 账号或密码错误}), 401 payload { user_id: user.id, username: user.username, exp: datetime.datetime.utcnow() datetime.timedelta(hours2) } token jwt.encode(payload, SECRET_KEY, algorithmHS256) return jsonify({code: 200, token: token})有几个细节我要专门提醒。第一生产环境绝对不能用固定的硬编码密钥我这个例子里写了占位符你自己的项目里至少要用一个安全随机生成的长字符串并且代码里只放到配置文件中。第二登录接口一定要做频率限制防止别人拿字典爆破密码最简单的做法是同一个IP或者同一个账号一分钟内最多尝试5次超出就锁一段时间。第三返回给前端的Token不要放在URL参数里浏览器历史会记录泄露风险很高正确做法是放在响应体里由前端存起来后续请求放进请求头。3.3 Token校验接口业务系统最依赖的入口业务系统接入认证中心核心要调用的就是Token校验接口。它的作用很简单收到业务系统传来的Token校验签名、校验过期时间、校验是否在黑名单里然后返回这个Token对应的用户信息。from functools import wraps def verify_token(token): try: payload jwt.decode(token, SECRET_KEY, algorithms[HS256]) except jwt.ExpiredSignatureError: return None, token已过期 except jwt.InvalidTokenError: return None, token无效 # 检查黑名单省略 Redis 查询逻辑 if is_in_blacklist(token): return None, token已失效 return payload, None app.route(/api/verify, methods[POST]) def verify(): token request.headers.get(Authorization, ).replace(Bearer , ) payload, err verify_token(token) if err: return jsonify({code: 401, msg: err}), 401 user find_user_by_id(payload[user_id]) return jsonify({ code: 200, user_id: user.id, username: user.username })这个接口设计成POST而不是GET是因为GET请求容易被日志系统或浏览器插件记录下来Token通过POST的请求体传递更安全。业务系统调用时把JWT放在Authorization请求头里这是一种约定俗成的标准用法。这里顺便讲一下为什么业务系统本地就能校验Token却还要调接口。实际上很多轻量接入方确实可以只在本地用公钥验签不需要每次请求都来问认证中心这样性能更好。但毕设项目里保留一个verify接口意义在于一是演示起来更直观二是黑名单机制必须有这个入口三是如果Token里携带的权限信息需要实时更新集中校验更方便。你可以把两种方式都写在文档里说明各自的适用场景这会显得你对方案的理解更透彻。3.4 模拟两个业务系统的SSO演示很多人做完认证中心不知道怎么演示单点登录的效果。我的经验是用两个简单的前端页面模拟业务系统分别跑在不同的端口一个8001叫教务系统一个8002叫图书系统。用户先访问8001页面弹提示未登录自动跳转到认证中心地址比如5000端口。用户在认证中心登录成功后被重定向回80018001的后端拿着Code换到Token。此时页面显示当前登录用户并能调用一个受保护接口返回模拟数据。接着不关闭浏览器直接访问8002你会发现系统没有要求重新登录而是直接进入了已登录状态。这个无感登录的过程就是整个项目最惊艳的演示点。实现这个效果时最需要注意的是授权码的流转。业务系统后端拿到Code后要带上自己的应用ID和应用密钥再调用认证中心的换Token接口这一步一定要由后端完成绝不能在前端完成否则应用密钥会暴露在浏览器里任何人都有机会冒充业务系统。为了让答辩更生动还可以在认证中心加一个已登录应用列表显示当前会话登进过哪些系统。这样用户访问8001和8002后回到认证中心看到两个系统的登录记录整个SSO链路就形成了闭环一眼就能看懂。3.5 登出与Token失效处理登出功能看似简单其实也有讲究。我的方案是认证中心提供一个登出接口把当前Token加入Redis黑名单同时清掉认证中心域名下的登录Cookie。app.route(/api/logout, methods[POST]) def logout(): token request.headers.get(Authorization, ).replace(Bearer , ) payload, _ verify_token(token) if payload: # 将 token 加入黑名单过期时间与 token 剩余时间对齐 remaining payload[exp] - int(datetime.datetime.utcnow().timestamp()) add_to_blacklist(token, remaining) return jsonify({code: 200, msg: 登出成功})为什么登出后还要保留Token直到它自然过期而不是立刻让它失效因为JWT是无状态的认证中心无法主动通知所有业务系统这个用户登出了所以只能通过黑名单机制来临时禁用。把黑名单的过期时间设置成与Token剩余寿命一致既保证登出后Token立即不可用又不会让黑名单无限膨胀占内存。真正要全局踢人下线更彻底的做法是在用户表里加一个token_version字段每次生成Token时把版本号写进载荷校验时对比数据库里的当前版本版本不一致就拒绝。这种方法适合修改密码后踢掉所有旧会话、管理员强制下线某个用户这类场景。毕设里能做到登出进黑名单已经很不错如果再把版本号方案提一嘴就属于超纲加分了。4. 实操中的常见问题与排坑记录4.1 跨域问题认证中心和业务系统不是一家人跨域是这类多系统项目里最容易把人卡住的问题而且报错信息对新手很不友好浏览器控制台里一串英文实际含义就是你的浏览器拒绝这个请求携带身份信息。认证中心在5000端口业务系统在8001端口前端从8001页面发起向5000的请求端口不同就是跨域。解决思路分两层。第一层是后端允许跨域在Flask里用flask-cors库配置允许的域名和请求头注意Authorization请求头必须显式加进allowed_headers否则前端带Token的请求依然会被拦。第二层是Cookie的SameSite属性如果SSO依赖Cookie判断已登录状态跨域场景下浏览器可能直接把Cookie丢掉需要把SameSite设置为Lax或者None但设置了None就必须配合Secure属性也就是只在HTTPS下生效开发环境可以用localhost来绕过。我踩过的坑是在本地环境用127.0.0.1调试时一切正常换成localhost就出问题。原因是Cookie的Domain匹配机制把IP和域名当成两个不同的源。建议从一开始就统一用localhost访问所有服务省掉一整类莫名其妙的问题。4.2 前端要做的三件事保存、携带、刷新很多同学做完后端接口发现前端不知道怎么配合。这里有个基本功得理顺。第一步前端收到登录接口返回的Token后存到localStorage或sessionStorage里注意不要存到Cookie里否则又会引入CSRF跨站请求伪造风险。第二步封装统一的请求工具在发起每个请求时从存储里取出Token放到请求头const token localStorage.getItem(token); fetch(/api/user_info, { headers: { Authorization: Bearer ${token} } });第三步处理Token过期。JWT设置了两小时过期用户用了一个半小时后请求接口返回401这时前端要捕获这个状态自动跳转到认证中心重新登录而不是弹一个让人摸不着头脑的报错框。比较体面的做法是加一个Refresh Token机制访问Token过期了用Refresh Token去换新的访问Token用户无感知。但Refresh Token本身也需要安全存储和复用限制毕设里如果做不好建议老实做过期就重新登录就好至少体验一致、逻辑闭环。4.3 安全细节密码、防刷、防泄露这个项目最容易被答辩老师翻来覆去问的就是安全问题提前准备几个标准答案有备无患。密码存储上面说过必须加盐哈希绝不允许明文。这一点是底线老师一问你的密码库泄露了怎么办如果你回答我用的bcrypt加盐哈希即使用户密码库被拖走破解单个密码的成本也非常高场面就稳了。接口防刷登录接口必须限流。最简单的实现是Redis里存一个计数器键名是login:尝试次数:用户名IP一分钟内超过5次就拒绝并提示尝试次数过多请稍后再试。这能有效挡住低成本的暴力破解。Token防泄露后端统一在所有响应头上加Cache-Control: no-store防止浏览器缓存包含Token的页面前端不要在任何URL参数里传Token所有会话相关的接口建议走HTTPS。虽然是毕设但你在文档里写明这些点答辩水平立刻和其他能跑就行的项目拉开差距。关于日志和隐私不要记录密码、Token等敏感字段只记录登录结果和IP也顺便回应了最小化数据收集的通用要求。4.4 一套好用的排错思路多系统协作的项目出问题后第一反应很重要。我的建议是从近到远、逐层排查。前端报401先看请求是不是真的带上了Authorization头再确认Token是不是过期了最后把Token放到jwt.io这类工具上检查签名算法是否符合预期。前端跳转到认证中心后一直回不来优先检查回调地址参数是否编码正确认证中心返回给业务系统时是否仍然用同一个回调地址。业务系统换Token换不到检查应用ID和应用密钥是否配对、认证中心白名单里有没有登记这个回调地址。只要养成看请求、看响应、看日志三步走的习惯大部分问题能在十分钟内定位。我在做这个项目时最常用的就是浏览器的开发者工具F12打开网络面板把每个请求的请求头、响应体看一遍问题基本就水落石出了。5. 怎么把同一个题目扩展到其他方向5.1 换语言实现Java和PHP的思路很多学校要求毕设必须用Java或者你手头只会PHP其实完全不用慌。统一身份认证的核心是思路不是语言同一个方案可以平移。Java首选Spring Boot加Spring Security天然支持OAuth2和JWT。你甚至不需要自己手写JWT签发用spring-security-oauth2-jose和spring-security-oauth2-resource-server就能把认证中心和资源服务搭出来代码量比Python版更少。答辩时还能讲一嘴Spring Security的过滤器链机制这属于加分项。PHP的话用Laravel的Passport包或者直接用原生PHP配合firebase/php-jwt这个库也很方便。Laravel自带用户认证体系改造一下登录返回逻辑就能签发JWT。如果学校允许原生PHP就自己写一个Token工具类原理完全相同。换语言时最需要移植的其实是三样东西JWT签发与校验逻辑、密码哈希存储逻辑、授权码的生成与一次性消费逻辑。把这三点想透了任何一门后端语言都能写出认证中心。5.2 接App、小程序和数据可视化如果毕设题目挂的是App或小程序统一身份认证依然能升级复用。App端和Web端最大的区别是没有浏览器帮你管理Cookie和跳转所以App通常采用纯Token方案用户在登录页输入账号密码认证中心返回TokenApp持久化保存后续所有请求带上Token。如果想做扫码登录额外加一个轮询逻辑App扫描认证中心展示的二维码二维码里带上一个临时标识App确认登录后认证中心把会话标记为已确认浏览器端轮询到已确认就跳转。这个功能看起来高级实际实现也就增加两个接口。小程序端更特殊微信自己有wx.login体系但毕设完全可以做成自建账号体系流程和App一致只是请求工具换成wx.request。数据可视化就更好接了把登录日志里的用户ID、登录时间、IP地址按小时、按系统维度做聚合统计用ECharts或者Python的Flask加一个前端页面展示活跃趋势图。我见过最讨巧的做法是做一个认证中心运营大屏左侧登录趋势折线图右侧各系统接入情况饼图中间滚动最近登录记录整体效果非常唬人做起来却一点也不难。5.3 和爬虫结合给自动化采集做一个正规入口项目标题里出现了爬虫很多人第一反应是Scrapy框架、requests库、网页解析但这些和统一身份认证有啥关系实际上是有的而且关系很自然。很多数据采集场景不是爬公开网页而是要采集需要登录才能看到的数据。在没有认证服务时你只能模拟登录、硬啃加密参数、和反爬机制斗智斗勇。如果项目里有统一身份认证你可以把它当做一个合法的身份获取入口先用账号密码调用认证中心的登录接口拿到Token再拿这个Token去请求业务系统的数据接口整个采集过程就走上了正规、可控的路径不需要逆向任何加密参数也大大减少了被反爬机制误伤的概率。需要强调的是这种用法只适用于你有合法授权的情况比如你自己的项目、内部系统的数据归集。做毕设也罢、做研究也罢采集之前一定要搞清楚数据的使用边界遵守网站的服务条款和robots协议不做任何越权的尝试。把通过认证中心统一获取身份凭证再访问数据接口这个设计放在论文里导师会觉得你考虑的不仅是技术还有工程规范印象分会更好。5.4 论文和演示录像怎么做出彩最后说点答辩实用技巧毕竟很多同学做完系统不知道怎么在论文和演示环节把亮点讲足。论文结构上我建议至少保证这些内容背景与意义里写清多系统账号孤岛的痛点核心技术和相关研究里把JWT、单点登录、OAuth2这些概念的演变讲清楚系统设计章节放架构图、数据库ER图、接口时序图实现章节按模块写并配核心代码片段测试章节记录功能测试和安全测试的结果。论文里不需要贴完整代码但一定要有设计思路的说明文字这比代码本身更能体现工作量。演示录像我踩过的坑是录屏时忘了先把服务全部启动好结果边录边等启动观众体验很差。正确流程是先启动认证中心、两个业务系统、Redis全部就绪后再开录。录的时候按这个顺序走首页介绍项目背景展示数据库表然后演示未登录访问被重定向、登录成功回跳、跨系统无感登录、登出后Token失效最后补一个安全测试画面错误密码连续输入被锁定。全程控制在六分钟内节奏紧凑比拖沓的十几分钟效果好得多。还要提醒一句演示时准备一个干净的测试账号密码设置得简单一点避免现场输入错误导致尴尬。如果现场网络不稳定优先把Redis、MySQL都切到本地模式不要让演示依赖外网。6. 最后再分享一点我的经验我在实际做这类认证项目时最大的体会是校内的毕设题目真正拉开差距的不是功能数量而是边界意识。统一身份认证这种题目功能列表可以无限长——验证码、扫码登录、短信登录、第三方OAuth接入、权限管理、审计报表样样都能加。但一个合格的毕设核心不是堆功能而是把你选定的那几条链路做到闭环、做得严谨。登录、校验、登出、授权码交换这四个核心环节每一个的异常情况都要处理到位比多做一个花哨页面重要得多。同样值得说的是千万不要直接拿现成源码跑通了就算完事。白嫖的源码可以供你参考但如果你在答辩时连自己项目里的SECRET_KEY放在哪个文件、黑名单为什么用Redis、业务系统为什么不能直接拿用户密码这些基础问题都答不上来老师一眼就能看出来。安全的做法是参考别人的源码理清思路再把核心模块自己重写一遍尤其是JWT签发与校验、授权码交换这两个环节用你自己的语言和风格来实现。我个人一直觉得毕设最理想的状态不是做出来一个完美无可挑剔的产品而是把你做过的每一个技术决定都能说出理由。统一身份认证恰恰给了你这样的空间为什么用Token不用Session为什么授权码要用一次性的为什么业务系统不能直接碰密码这些问题没有标准答案但每个都对应一条清晰的技术逻辑。你把这个逻辑讲通了分数自然不会低。
返回列表