先进行页面设计和开发,以驱动后端开发
技术:
- CodeGenerator 自动生成对表的增删改查——mybatis-plus 插件
- 统一结果封装 Result 类
- shiro+jwt(登录时,后端校验通过则返回 jwt,后续客户端请求携带 jwt 作为身份凭证);过滤器JwtFilter处理 jwt(有则交给shiro登录处理:将 jwt 封装成 token、利用shiro的 manager 进行登录 。如果发现 jwt 异常,则解析 Jwt,获取用户 ID,利用 ID 从数据库中找到用户数据,判断数据是否正常,如过期、密钥不对,应抛出异常,应利用全局异常处理器进行拦截,然后返回 json 数据给浏览器 ;如正常则可以访问接口,但有些需要访问权限的请求需要用shiro注解过滤形式进行前置拦截,如@RequireRoles(“admin "),当访问者无权限时抛出异常,全局异常捕获),shiro主要进行登录处理,其他权限校验交给注解过滤处理。
- hutool 工具,处理业务,简化代码
被@Component注释的类,不需要创建方法返回该类对象并加@Bean 以注入,可以@Autowired自动注入
springboot项目中调用第三方jar包中的类时报错,在主配置类上加上@ComponentScan注解,扫描对应包
实体校验,校验表单(如登录表单),使用 Hibernate validator 框架
全局异常处理
controller 方法中的@RequestBody 将请求主体内的 Json 数据转为实体,在实体前面加@Validated 注解来触发实体校验,如果有异常MethodArgumentNotValidException(实体校验异常)会抛出,后被全局异常处理捕获(对异常的重要信息进行提取作为 Result 的 message并发回前端,一般只返回第一种异常
跨域问题处理:JwtFilter 中跨域处理preHandle(在其他处理之前进行的)、配置 CorsConfig。后续学习背后原理https://tech.meituan.com/2018/10/11/fe-security-csrf.html讲的很好
shiro+jwt
1、处理流程
2、导入 Shiro-redis 的 jar 包 shiro-redis-spring-boot-starter
编写 ShiroConfig 配置类,要对 SessionManager 和 DefaultWebSecurityManager进行重写(@Bean),解决shiro的权限数据和会话信息能保存到redis中,实现会话共享。
AccountRealm
AccountRealm是shiro进行登录或者权限校验的逻辑所在,算是核心了,我们需要重写3个方法,分别是
- supports:为了让realm支持jwt的凭证校验
- doGetAuthorizationInfo:权限校验
- doGetAuthenticationInfo:登录认证校验
3、代码追踪
JwtUtils 工具类:实现登录校验,校验 jwt 是否过期、用户密钥是否匹配
generateToken(long userId):生成 jwt token,jwt.builder()方法生成 jwts,填入userId、过期时间等参数
getClaimByToken:利用Jwts.parser()校验 jwt token
isTokenExpired:expiration.before(new Date())判断是否过期
JtwFilters 对所有请求进行过滤
createToken:用户登录时,从请求中获取 jwt(包含用户名和密码),如果有,则用 token封装 jwt(AuthenticationToken类型对象),
onAccessDenied:接受到有jwt 并封装成 token之后, 还需要判断 jwt 是否过期等异常。 没问题则执行自动登录
onLoginFailure:当登录出现异常(超时,用户不存在等)Realm的doGetAuthenticationInfo会抛出异常,会触发此方法,要向浏览器返回 JSON 数据
preHandle
需求设计
用户故事——敏捷开发方法
角色:访客、管理者
管理者:
- 推荐博客到首页
- 后台管理系统登录
- 发布博客,发布博客时选择标签、可新增标签;修改、删除
访客:
- 查看所有博客:(1)按照点赞数量全排序 (2)按照标签进行展示
(3)按照撰写时间展示,选择时间范围(从新到老排序)(可以放在按标签展示内部)- 搜索博客(模糊搜索,匹配文章名、文章内容
或文章摘要内容)- 对博客进行点赞、评论
- 微信扫码阅读博客内容、关注我的公众号
功能规划
1、前端展示
首页:推荐博客版块、分类(标签)列表板块、点赞数排行板块
分类(标签)列表页面:展示所有分类、分类下的博客列表
点赞数排行板块:按照点赞数量从高到低进行展示
2、后端管理
注册和登录(可以由多个人进行发布)、博客的增删改查
3、小技术点
代码语法高亮展示、markdown 使用
页面设计
使用工具 Axure RP 8(bs3元件库)
导航:首页、标签、点赞、搜索
登录和登出
登录的逻辑其实很简单,只需要接受账号密码,然后把用户的id生成jwt,返回给前端,为了后续的jwt的延期,所以我们把jwt放在header上。具体逻辑如下:
技术:
- 利用 Assert 工具,用于判断是否为空,如果为空会携带自定义错误信息抛出IllegalArgumentException(在全局异常处理捕获)
- 使用 MapUtil.builder.put( " ", ).put().map()直接生成 map 对象(在生成Result 中的 data 时使用)
- 响应头部字段Authorization、Access-Control-Exposed-Head的用法
登录逻辑:
- 接收请求参数,对请求主体封装(利用loginDto封装前端发来的用户名和密码)和实体校验(对用户名密码非空校验:增加@Validated注释,从而触发对loginDto中定义的规则的校验——Hibernate validator 框架)
- 利用用户名获取数据库 user 表数据,并检测数据库查询结果是否异常:(1)利用Assert工具判空,为空表示用户不存在则抛出异常(2)数据库查出的密码(md5加密后存储)和请求中的密码进行md5加密的结果不相等,则返回Result.fail("密码不正确")
- 不存在异常,则利用封装的 jwtUtils 生成 jwt token(包含数据库中 user 信息对应的 id,之后对于携带 jwt 的请求,服务器从 jwt 的 subject 能拿到 userId)。将 jwt 加入 响应返回头部(添加首部字段 Authorization,值为 jwt;并添加 Access-Control-Exposed-Head,值为"Authorization",使得浏览器能从响应报文中获取Authorization字段的 value),并创建 map (包含 userID、username、邮箱、等从数据库查到的信息)作为主体返回给浏览器
登出:
交给 Shrio 直接退出
博客
BlogController、Blog 添加校验
博客编辑或添加请求:添加@RequiresAuthentication注解,表示该请求需要认证之后才能访问