Token+swagger记得推 分布式
enable能 使
Swagger:类似于在线的javaDoc,直接运行,在线测试API 他是前后端联调的工具
API 应用程序的接口
1.1 Spring集成Swagger
两种------springfox-swagger2 swagger-springmvc 这里的示例 第一种
往接口上写注解(接口是controller里面提供的那些接口)
1.2 常用注解
(1)@Api 用在请求的类上 表示对类的说明
示例:
@Api(tags = "注册控制器")
@RestController
@RequestMapping("/api")
public class RegisterController {
结果显示:/swagger-ui.html必须要写
(2)@ApiOperation:用在请求的方法上,说明方法的用途、作用
常用参数:
value=“说明方法的用途、作用”
notes="方法的备注说明"就是详细信息
httpMethod 指定HTTP方法,“GET”, “HEAD”, “POST”, “PUT”, “DELETE”, “OPTIONS” and “PATCH”
produces 设置MIME类型列表(output),例:“application/json, application/xml”,默认为空
protocols 设置特定协议,例:http, https, ws, wss。
(3)@ApiImplicitParams:用在请求的方法上,表示一组参数说明
单数是写在复数里面的
方法的参数如果为对象:
(4)@ApiModel:用于响应类上,表示一个返回响应数据的信息(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候)
@ApiModelProperty:用在属性上,描述响应类的属性
value 此属性的简要说明。
@ApiIgnore: 用在请求方法上,用于忽略对应方法,一般用于内部接口 生成的doc文档里面不显示此接口
<mvc:default-servlet-handler>mvc:default-servlet-handler>
在线测试
最后访问的时候
分布式开发
考虑登录session问题
考虑第三方登录的问题
1.前端和后端分离(后端也是多模块部署),Session信息无法共享
2.前端可能是移动端App,无法使用Session
1.登录用户的来源(情况)
自注册用户
第三方登录的用户
内部注册(第一次使用第三方 随机帐号和密码等信息)
2.分析传统的登录实现
前端:填写帐号和密码
后端:接收帐号和密码
验证帐号和密码是否存在且正确
失败:
跳转回登录页面
提示用户名或密码错误!
成功:
将用户的部分帐号信息存储到Session作用域(一个用户来访问正好对应一次会话)
跳转到项目主页
3.分析分布式情况的登录实现
自注册用户:
前端:填写帐号(手机号)和密码
后端(auth):接收帐号和密码
验证帐号和密码是否存在且正确
失败:(DTO)
返回提示,用户名或密码错误!
成功:
【存储用户的部分帐号信息】
…
第三方登录用户:
前端:用户点击对应的第三方登录图标
后端(auth):接收用户到底要使用何种第三方登录方式
…(学习如何接入第三方 验证信息)
失败:
返回提示,第三方登录失败!
成功:
检查当前用户是否存在
存在:
【接入自注册用户的成功部分业务实现】
不存在:
进行第三方登录用户的注册(随机帐号、密码等信息)
【接入自注册用户的成功部分业务实现】
【原版Session的大致流程】原版的Session不仅仅用于登录后用户信息的存储
1.浏览器访问项目服务器
2.服务器接收到此次访问之后,验证当前浏览器是否携带了指定的cookie信息(JSessionId)
没有携带:(第一次访问/Session已经过期)
会根据浏览器等信息来生成一个唯一的会话标识(JSessionId),并且会为其准备一块区域用于存储信息
在响应的同时,服务器会将此标识通过cookie响应到浏览器(默认的cookie是会话级,浏览器关闭即cookie销毁)
携带:
服务器开放浏览器访问对应Session区域的权限
浏览器也可以实现携带类似的JsessionId(请求头 request header)
浏览器也可以在本地缓存(接收)服务器响应回来的类似的JsessionId(Cookie存储)
token 生成算法设计如下:
例如:PC端:PC-121adv212das-1-201908281128-123456
PC 端: token:PC-USERCODE[加密]-USERID-CREATIONDATE-RANDEM[6位]
移 动 端 : token:MOBILE-USERCODE[加密]-USERID-CREATIONDATE-RANDEM[6位]
redis和服务器独立 session是服务器里面的 redis是服务器外面的 他们之间是独立的
Redis中存储键值对
键:token:PC-121adv212das-1-201908281128-123456
值:用户的部分帐号信息
Session默认过期时间为:30分钟(用户无操作)
Session在浏览器关闭之后会进行销毁(会话级Cookie消失了)
Redis可以设置键的存活时间
PC端:set(“token:PC-121adv212das-1-201908281128-123456”,【2小时】,用户的部分帐号信息)
用户如果一直在操作是不能进行销毁的:
我们通过前端的【置换请求】(前端自行判断,在还剩5分钟过期的时候还在操作)来界定用户是否还在操作。
前端通过服务器最初响应的Token的信息来界定:
Token的ID
Token的生成时间 2019.8.28 11:43
Token的过期时间 2019.8.28 13:43(未来前端 通过当前时间来和过期时间进行计算)
为了保证Token的安全性,我们在快要过期时,接收到了前端的【用户置换】请求,进行Token信息置换
置换成功之后将信息重新响应给客户端。
假设:
前端用户还有30分钟过期
,用户开始进行酒店预定。(前端1.5小时之后可以置换)
预定酒店请求 -> 携带着老Token信息 访问后端
为了防止出现请求并发时 老Token失效问题 将老Token额外存储2分钟
置换Token请求 -> 携带着老Token信息 访问后端 -> 响应新的Token(Redis也换了Token信息)
新的请求 -> 携带着新Token信息 访问后端
移动端:set(“token:MOBILE-121adv212das-1-201908281128-123456”,【“永久”】,用户的部分帐号信息)
为了简化开发,省略了【secrect key/ticket秘钥】
用户退出功能 就是把redis里面的token信息进行删除
生成Token的时候 可以通过User-Agent判断是客户端还是服务器端
//@RequestHeader获取请求头信息
@RequestMapping(value="/dologin",method= RequestMethod.POST)
public Dto doLogin(@RequestParam String name, @RequestParam String password, @RequestHeader("user-Agent") String userAgent){
String userTokenJson = JSON.toJSONString(itripUserTokenVO);
//json作用 对象封装成字符串
//存储部分用户信息
ItripUserTokenVO itripUserTokenVO=new ItripUserTokenVO();
//把itripUserTokenVo里面的信息赋值到itripUser中
BeanUtils.copyProperties(itripUser,itripUserTokenVO);