【课程八】预防xss...注入.xmind0.2MB
【课程八预习】开...解读.xmind0.5MB
课程八_日志处理与...模块.xmind0.2MB
【课程八】redis的使用.xmind44.7KB
【课程八】renren_f...总纲.xmind0.5MB
【课程八】前后端...机制.xmind0.3MB
【课程八】优雅处理异常.xmind32.7KB
开发文档:
renren-fast开发文档2....整版.pdf2.2MB
项目介绍
- renren-fast是一个轻量级的 Spring Boot 快速开发平台,能快速开发项目并交付【接私活利器】
- 完善的 XSS 防范及脚本过滤,彻底杜绝 XSS 攻击
技术选型
后端
前段
功能描述
前段部署
由于前端使用vue开发,因此需要安装node.js环境。
node.js安装教程:http://nodejs.cn/download/ 下载msi版本安装。
安装之后,命令行窗口,表示安装成功。
启动步骤:
# 克隆项目
git clone https:
# 切换到项目目录根目录renren-fast-vue里面
# 安装依赖
# 1
npm install -g cnpm --registry=https:
# 2
cnpm install
# 启动服务
npm run dev
系统日志
系统管理员的有很多,操作权限也不同,但每个人的操作都需要有个操作记录才能跟踪每个管理员的操作,便于排查事故。
关键类
- io.renren.common.annotation.SysLog
- io.renren.common.aspect.SysLogAspect
项目逻辑
- 自定义方法级别的注解SysLog,在需要说明操作日志的方法上添加此注解,并说明操作的意义。
@SysLog("保存菜单")
- 同时编写切面处理类SysLogAspect,使用SysLog作为切入点,监测注解的方法。并把操作内容保存到数据库中。操作内容包括:调用的方法,参数,时间点,操作用户,操作ip地址等~
前后端分离-token机制
一般情况下,web项目都是通过session进行认证,每次请求数据时,都会把jsessionid放在cookie中,以便与服务端保持会话。本项目是前后端分离的,通过token进行认证(登录时,生成唯一的token凭证),每次请求数据时,都会把token放在header中,服务端解析token,并确定用户身份及用户权限,数据通过json交互。
项目设计
- --> SysLoginController中login()方法验证账号密码
- --> 生产token保存到数据库中,并返回给数据库
- --> logout()方法退出的操作就是把数据库中该用户的的token改成新的。
- --> token的验证交给shiro处理,OAuth2Filter过滤器那里开始。
前后端分离的意义
试想一下,如果前端掌握了Controller,我们可以做url design,我们可以根据场景决定在服务端同步渲染,还是根据view层数据输出json数据,我们还可以根据表现层需求很容易的做Bigpipe,Comet,Socket等等,完全是需求决定使用方式。
MVVM模式
模型
模型是指代表真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心)。
视图
就像在MVC和MVP模式中一样,视图是用户在屏幕上看到的结构、布局和外观(UI)。[6]
视图模型
视图模型是暴露公共属性和命令的视图的抽象。MVVM没有MVC模式的控制器,也没有MVP模式的presenter,有的是一个绑定器。在视图模型中,绑定器在视图和数据绑定器之间进行通信。
拓展知识1--session与cookie
由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached、redis之类的来放 Session。
思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
所以,总结一下:
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式
拓展知识2--单点登录
session的单点登录实现方式
jwt的单点登录实现方式
拓展知识3--预防CSRF攻击
跨站请求攻击,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一定的操作。因为浏览器认证过,所以网站会认为是真正的用户在操作。
例子
假如一家银行转账操作的URL地址如下:
http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName
那么,一个另外的网站可以放置如下代码
<img src="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">
如果用户之前刚访问过银行网站,登陆信息尚未过期,再次访问恶意网站点击了这个图片,那么就会损失1000元。事实上,这些地址还可以放在论坛、博客等地方,这种恶意访问的形式更加隐蔽,如果服务端没有相应措施,很容易受到威胁。
防御措施
检查referer字段
HTTP头中有一个Referer字段,这个字段是用来标明请求来源于哪一个网址。通常来说,Referer字段应和请求的地址是在同一个域名下的。服务器可以通过判断Referer字段来判断请求的来源。
这种方法简单易行,但也有其局限性。http协议无法保证来访的浏览器的具体实现,可以通过篡改Referer字段的方式来进行攻击
自定义异常-优雅处理异常
自定义异常类RRException
系统自带的,系统自己处理,但是很多时候项目会出现特有问题,而这些问题并未被java所描述并封装成对象,所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题进行自定义异常封装。在Java中要想创建自定义异常,需要继承Throwable或者他的子Exception。
class 自定义异常类 extends 异常类型(RuntimeException){
}
spring boot统一异常处理
主要注解:@ControllerAdvice、@ExceptionHandler
全局异常处理@ControllerAdvice。
添加@ControllerAdvice注解的类是集中处理异常的地方,可以同时存在多个这样的类,用来做更细粒度的划分。
在这个类中,我们可以对每一种异常编写一种处理逻辑,在方法上使用@ExceptionHandler注解修饰,传入指定的异常类型即可。
如果是RESTful风格,不返回视图,也可使用@RestControllerAdvice
@RestControllerAdvice是一个组合注解,组合了@ControllerAdvice、@ResponseBody
redis的使用
官方给出的redis使用原则
1. 查询数据的时候,尽量减少DB查询,DB主要负责写数
2. 尽量不使用 LEFt JOIN 等关联查询,缓存命中率不高,还浪费内存
3. 多使用单表查询,缓存命中率最高
4. 数据库 insert 、 update 、 delete 时,同步更新缓存数据
5. 合理运用Redis数据结构,也许有质的飞跃
6. 对于访问量不大的项目,使用缓存只会增加项目的复杂性。
Redis切面处理类RedisAspect,使用切面定义是否启用redis缓存。
redis开关原理
ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法,当不打开redis缓存时候,跳过RedisUtils的所有方法执行。
- SysConfigRedis,系统配置缓存操作的工具类
数据校验
后端效验使用的是Hibernate Validator校验框架。且自定义ValidatorUtils工具类,用来效验数据。
通过分析上面的代码,我们来理解Hibernate Validator校验框架的使用。
其中,username属性,表示保存或修改用户时,都会效验username属性; 而password属
性,表示只有保存用户时,才会效验password属性,也就是说,修改用户时,password可以
不填写,允许为空。
如果不指定属性的groups,则默认属于javax.validation.groups.Default.class分组,可以通
过ValidatorUtils.validateEntity(user)进行效验。
项目逻辑
- 首先定义分组,根据实际情况,可以分为添加组AddGroup和修改组UpdateGroup等。
- 在实体上添加hibernate.validator规则注解@NotBlank、@Email等,并分组。
- 编写规则校验工具类ValidatorUtils。校验出有不符合规则的内容抛出自定义异常RRException
- 再保存、更新等操作中使用ValidatorUtils.validateEntity(user, AddGroup.class);校验实体规则情况。
常用注解
Bean Validation 中内置的 constraint
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内