记录一次从github上一个项目学到的东西

记录一些从一个项目中学到的一些东西

原作者项目地址
oyh980707/store: 基于Springboot SSM框架的电子商务商城项目 (github.com))

学到一个登录的写法,把盐值也随机,更安全了,把盐值也存到数据库,然后for循环3次md5加密了,判断时候,把盐值和密码都取出来然后判断

		// 从数据库得到盐值
		String salt = result.getSalt();
		// 基于参数中传过来的的password进行加密,得到加密后的密码
		String md5Password = getMd5Password(password, salt);
		//将加密后的密码与数据库存的加密后的密码比较

三次加密

// 得到盐值
		String salt = result.getSalt();
		// 基于参数中的password进行加密,得到加密后的密码
		String md5Password = getMd5Password(password, salt);

还有就是学到一种写法,在service层写私有方法去调用mapper,然后在service层要实现的抽象方法里去调用私有方法的写法

	@Override
	public List<Goods> getNewList() {
		return findNewList();
	}
private List<Goods> findNewList() {
		return this.goodsMapper.findNewList();
	}

如果字段有公共的,可以写个公共的实体类,然后其他实体类去继承,每个表还可以加个修改者的字段

image-20221003210405036

/**
 * 实体类的基类
 *
 */
abstract class BaseEntity implements Serializable {
	private String createdUser;
	private Date createdTime;
	private String modifiedUser;
	private Date modifiedTime;
	
public class Address extends BaseEntity {
	private static final long serialVersionUID = 6946915401608396201L;

	private Integer aid;
	private Integer uid;
	private String name;
	private String provinceCode;
	private String provinceName;
	private String cityCode;
	private String cityName;
	private String areaCode;
	private String areaName;
	private String zip;
	private String address;
	private String phone;
	private String tel;
	private String tag;
	private Integer isDefault;

关于VARCHAR的设置

在MySQL数据库中,如果某字段的类型设置为VARCHAR(30),表示访字段最多存储30个字节长度的数据,如果尝试存入的数据超出30字节,多余的部分将不会被存储!

30个字节,表示为多少个字符,取决于使用的字符编码!

以UTF8为例,如果存储的内容是1个字节的,存储下来例如:

0110 0001

其规则是使用第1位0表示该字符只占1个字节,剩余的7位表示1个字符!

如果某个字符需要使用2个字节才可以表示,UTF8的规则表现例如:

110 01010	10 000111

即第1个字节使用110作为前缀,表示该字符需要2个字节,其中,这里的2个1就表示共要2个字节,后续的第2个字节中的10就表示它是跟随前序字节一起的,第2个字节中的剩余6位才是编码位。

在2个字节中,只有5+6=11个编码位,只能表示2048种不同的组合,所以,在UTF8编码中,2个字节是不可以表示中文的,因为中文里的汉字数量及相关符号远超2048个!所以,中文需要3个字节来表示,在UTF8中,3字节的编码例如:

1110 0101	10 101010	10 010101

在UTF8中,还有需要4字节才可以表示的编码……

所以,如果设计的是VARCHAR(30),并使用UTF8编码,到底可以存入多少字符,也是不确定的,如果存的是ASCII字符,最多可以存30个,如果存的是汉字,只能计划为10个,如果是混合的,可以计划为例如15个英文加上5个汉字……所以,通常,在设置时,只能根据最大需求来进行设计!

另外,请还注意一个问题:设置的字节值,并不代码存储占用空间!例如将VARCHAR(30)存满,还另外会占用1个字节存储长度,表示存了多少字节的数据,在存储长度时,数据类型的字节数在255个时是分隔线,如果使用VARCHAR设置的字节数超过255,则另外需要占用2个字节存储长度!例如设置VARCHAR(300),则额外的存储长度时使用字节数就是2个字节!

密码加密

加密算法并不适合对密码进行加密!因为,所以的加密算法都是可以逆运算的,如果使用的算法和加密时使用的参数是已知的,则可以轻松推算出原始数据!而密码安全问题主要源自内部泄密!也就是说,数据库的数据能泄密,可以认为算法和加密参数也是有泄密的可能的!

对于密码安全问题而言,最好的做法就是将密码进行加密,却任何人都无法解密!则,在密码加密这个问题上,所有的加密算法都是不适用的!只能使用摘要算法!

摘要算法的全称是“消息摘要算法”,这种算法的特征有:

  1. 消息原文相同时,得到的摘要是相同的;

  2. 使用的摘要算法没有发生变化时,无论原文长度是多少,摘要的长度是固定的;

  3. 消息原文不同时,得到的摘要几乎不会相同!

在消息摘要领域中,一定存在N种不同的原文,可以计算得到完全相同的摘要!

使用MD5算法执行摘要运算时,得到的结果都是32位长度的十六进制数,转换成二进制就需要128位,所以,MD5也被称之为128位的算法!

如果有2个不同的原文,可以得到相同的摘要,这种状况称之为“碰撞”,在有限长度的原文中,得到相同的摘要的概率是极低,甚至就是不可能的!

所以,真正用于对密码加密的算法,都是摘要算法,主要原因是因为它不可逆,且在有限长度的原文的基础之上,几乎不可能发生碰撞!

常见的摘要算法有MD5家族和SHA系列,例如:MD2、MD4、MD5、SHA1、SHA128、SHA256、SHA384、SHA512……其中,MD家族的都是128的,SHA系列名称后有位数的,就是对应的位数。

关于MD5或相关摘要算法的破解研究是存在的,主要是针对算法的碰撞攻击,而并不是尝试执行逆运算来得到原始数据!

另外,还有许多网站号称可以在线破解MD5,只需要将摘要结果填进去,就可以查到原始数据,例如填入e10adc3949ba59abbe56e057f20f883e就可以查出123456,事实上,这些网站是记录了大量的原始数据与MD5摘要数据的对应关系,如果原始数据比较简单,或者是常用密码值,被这些网站收录的可能性就非常大!所以,为了提升密码的安全性,保证密码不被这些网站“破解”,可以采取的做法:

  1. 增强原始密码的安全强度,例如从组成元素、长度方面提出更高要求;

  2. 反复执行加密,即多重加密;

  3. 加盐;

  4. 综合以上所有方式。

    select 原始数据 from 表 where 摘要数据=?

    10 + 52 + ? > 80

    1 > 80
    2 > 6400
    3 > 480000
    4 > 40000000
    5 > 3200000000

    8 >

    123456
    e10adc3949ba59abbe56e057f20f883e

    1
    c4ca4238a0b923820dcc509a6f75849b

    111111111111111111111111111111111111111111
    636fa4bad5bf92137374e947b3c424f0

设置SpringBoot项目上传限制

在启动类之前添加@Configuration注解,并在类中添加:

@Bean
public MultipartConfigElement getMultipartConfig() {
	MultipartConfigFactory factory = new MultipartConfigFactory();
	
	DataSize maxFileSize = DataSize.ofMegabytes(50);
	factory.setMaxFileSize(maxFileSize);
	DataSize maxRequestSize = DataSize.ofMegabytes(100);
	factory.setMaxRequestSize(maxRequestSize);
	
	return factory.createMultipartConfig();
}

SpringBoot项目RestController和Controller

@RestController注解相当于@ResponseBody + @Controller合在一起的作用。

  1. 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。

  2. 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。

基于Spring-JDBC的事务(Transaction)

首先,事务是用于保障数据安全的,可以使得一系列的增删改操作,要么全部成功,要么全部失败!

**什么情况下需要使用事务:**当某个业务涉及2次或更多次的增、删、改操作时,必须使用事务!例如执行2条Update语句,或1条Insert语句和1条Update语句等。

**如何使用事务:**基于Spring-JDBC的编程中,只需要在业务方法之前添加@Transactional注解即可。

框架在处理事务时,大致的执行过程是:

开启事务:begin
try {
	执行各任务
	提交:commit
} catch (RuntimeException e) {
	回滚:rollback
}

所以,为了保证@Transactional注解能够正常保障事务,在每次的增、删、改操作执行完成后,都必须判断受影响的行数是否是预期值,如果不是预期值,必须抛出RuntimeException或其某个子孙类的异常!

另外,@Transactional注解还可以添加在业务类之前,表示该类中所有的方法在执行时,都是有事务保障的!通常并不推荐这样处理!

数据的验证原则

通常,客户端应该完成数据的基本验证,然后才会将数据提交到服务器,所谓的基本验证通常指的是数据格式的验证,例如字符串的长度、字符串的组成、固定的格式等等。

当客户端完成了这些验证后,基本格式错误的数据将不会被提交的服务器!但是,并不是绝对的,当服务器接收到来自客户端的数据时,第一时间就应该再次验证这些数据!因为客户端是在用户自己手中的,是有可能被恶意篡改的,这一点服务器是无法把控的,所以,服务器并不能完全信任来自客户端的数据!

虽然服务器端会完成数据的验证,也并不代表客户端不需要验证,毕竟能够绕过客户端验证并提交的数据是少部分的,客户端的验证机制能拦截绝大部分数据有误的请求,从而减轻服务器压力!

甚至,在一些特殊的应用中,服务器端的Controller进行了数据验证,但是,Service还会再次验证!多半源自于这些应用中,Service并不一定是由Controller调用的,例如某些计划任务等。

所以,关于数据验证,需要验证的节点有:客户端、服务器端的Controller、服务器端的Service,各自解决不同的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值