2019_06_28 store密码加密_第二天

UserServiceImpl.java类中添加以下两段代码:

// 用户名未被占用,允许注册
		// 向参数user中补全属性:盐值
		String salt = UUID.randomUUID().toString().toUpperCase();
		user.setSalt(salt);
		// 取出参数user中的原始密码
		String password = user.getPassword();
		// 将原始密码加密
		String md5Password = getMd5Password(password, salt);
		// 向参数user中补全属性:加密后的密码
		user.setPassword(md5Password);
		// 向参数user中补全属性:isDelete-0
		user.setIsDelete(0);

多重加密
/**
* 执行密码加密,获取加密后的密码
* @param password 原密码
* @param salt 盐值
* @return 加密后的密码
*/
private String getMd5Password(String password, String salt) {
// 加密规则:使用“salt+password+salt”作为消息,执行3次摘要运算
String str = salt + password + salt;
for (int i = 0; i < 3; i++) {
str = DigestUtils.md5DigestAsHex(str.getBytes()).toUpperCase();
}
return str;
}

#################### 5.1 #####################
1.UserServiceImpl.java类中,添加密码加密和方法。
2.在业务层测试类中添加测试。
效果为:
1.控制台输出注册成功
2.数据库中密码显示是加密的。

6. 用户-注册-控制器层

(a)统一处理异常
创建类’cn.tedu.store.controller.BaseController’控制类的基类,
后续创建的每个控制器都应该继承这个基类,在基类中添加处理异常的方法,
则每个子级都拥有这个方法:

public abstract class BaseController {
	@ExceptionHandler(ServiceException.class)
		@ResponseBody
		public JsonResult<Void> handleException(Throwable e) {
			JsonResult<Void> jr = new JsonResult<Void>();
			jr.setMessage(e.getMessage());
		if (e instanceof UsernameDuplicateException) {
			jr.setState(2);
		} else if (e instanceof InsertException) {
			jr.setState(3);
		}

		return jr;
	}

}

}
(b) 设计请求

设计“用户注册”的请求方式:

请求路径:/users/reg
请求参数:User user
请求方式:POST
响应数据:JsonResult<Void>

© 处理请求

1.首先,需要创建cn.tedu.store.util.JsonResult响应结果类型:

public class JsonResult<T> {
	private Integer state;
	private String message;
	private T data;
	// SET/GET
}

2.再需要创建cn.tedu.store.controller.UserController控制器类,
在类之前添加@RestController@RequestMapping("users")这2个
注解,在类中添加声明@Autowired private IUserService userService;
业务层对象:

@RestController
	@RequestMapping("users")
	public class UserController extends xxxController {

		@Autowired
		private IUserService userService;

	}

3.接下来,在类中添加处理请求的方法:

@RequestMapping("reg")
	public JsonResult<Void> reg(User user) {
		JsonResult<Void> jr = new JsonResult<Void>();
		userService.reg(user);
		jr.setState(1);
		return jr;
	}

完成后,启动项目,打开浏览器,通过http://localhost:8080/users/reg? username=root&password=1234进行测试。

测试完成后,将方法之前的@RequestMapping替换为@PostMapping
(自己进行限制,也可以项目差不多完成之后再改成post请求的方式。)

#################### 以上大纲步骤 1 #####################

1.补充昨天的密码密码功能
2.添加控制层基类
3.添加响应结果的包和类
4.添加用户控制类
5. 测试效果为:
浏览器显示:
{“state”:1,“message”:null,“data”:null}

刷新后:
{"state":2,"message":"注册失败!尝试注册的用户名(root)已经被占用!","data":null}

#################### 代码调整 #####################

1.BaseController.java类中添加 操作成功时的响应状态代号
修改代码:
JsonResult jr = new JsonResult();
修改为:

JsonResult<Void> jr = new JsonResult<>();

2.JsonResult.java类中添加state构造方法

	public JsonResult(Integer state) {
		super();
		this.state = state;
	}

再添加一个无参的构造方法
3.JsonResult.java类中再添加一个message的构造方法
并修改为最大异常;

public JsonResult(Throwable e) {
		super();
		this.message = e.getMessage();
	}

BaseController.java类中的:

JsonResult<Void> jr = new JsonResult<>();

则可以修改为(多加了个e):

JsonResult<Void> jr = new JsonResult<>(e);

4.UserController.java类中:
修改代码:

@RequestMapping("reg")
	public JsonResult<Void> reg(User user) {
		JsonResult<Void> jr = new JsonResult<Void>();
		userService.reg(user);
		jr.setState(1);
		return jr;
	}
修改为:


@RequestMapping("reg")
	public JsonResult<Void> reg(User user) {
		userService.reg(user);
		return new JsonResult<>(SUCCESS);
	}

5.最后BaseController.java类中再添加代码
/**
* 操作成功时的响应状态代号
*/
protected static final Integer SUCCESS = 2000;

if (e instanceof UsernameDuplicateException) {
		jr.setState(4000);
	} else if (e instanceof InsertException) {
		jr.setState(5000);
	}

6.浏览器还是输入http://localhost:8080/users/reg?
username=root&password=1234并测试
效果为:2000和用户名重复:4000

7.项目完成之后需要将 UserController.java类中的权限改成@PostMapping
测试阶段可以暂时不修改

7. 用户-注册-前端界面

1.复制dom网页中学子商城下载的五个文件夹,放到项目static文加夹下
a.Ajax代码复制

b.register.htnl注册页面四个地方需要调整
	(a)有以下代码可以删除掉,不需要。
	$("#span-username").html("");
	(b)修改url路径
	(c)修改以下代码
	if(obj.state == 2000){
		alert("注册成功");
	} else {	
		alert(obj.message);
	}
	(d)修改表单id为"form-reg"
	名字和密码的input里面都要加上name=“相应的值”

	再次输入密码检查是客户端的事情,服务端不管。

	(e)立即注册按钮加上id="btn-reg"
具体的四个地方为:表单id、用户名和  密码的name 立即注册的id四个。
注意:老师导入项目:则需要四个前端页面的文件包复制进来,
不然则前端页面运行不了。

最后在浏览器输入前端页面的url进行测试:http://localhost:8080/web/Register.html
#################### 以上大纲步骤 2 #####################
1.修改UserMapper.xml中的查询代码。
2.UserMapperTests类中测试。
测试效果:控制台输出查询的数据
数据库中也能查到对应的数据。

8. 用户-登录-持久层

(a) 规划SQL语句

用户登录时,需要检查用户名是否存在,密码是否匹配,且is_delete的值是否表示“未删除”,关于“用户名”是否存在,可以通过查询数据库得到:

select * from t_user where username=?

如果查询到有效结果,则用户名是存在,可以进行后续的验证,如果查询的结果是null,则用户名尚未注册,不允许使用这个用户名登录!

关于密码、is_delete的验证应该在后续的业务层中进行判断,只需要保证以上查询时,能够查到与验证相关的字段即可,例如:

select password, salt, is_delete from t_user where username=?

并且,如果用户登录成功,还应该将用户(客户端)提供用户的相关数据,例如用户的用户名、头像,还需要在Session中记录该用户的id和用户名,则查询时还要查询这些字段:

select uid, username, password, salt, avatar, is_delete from t_user where username=?

(b) 接口与抽象方法

UserMapper.java接口中已经存在User findByUsername(String username)方法,则无需重复定义抽象方法。

© 配置映射

此次需要在findByUsername()方法的映射中补充查询更多的字段:

<!-- 根据用户名查询用户数据 -->
<!-- User findByUsername(String username) -->
<select id="findByUsername"
	resultType="cn.tedu.store.entity.User">
	SELECT 
		uid, username,
		password, salt,
		avatar, is_delete AS isDelete
	FROM 
		t_user 
	WHERE 
		username=#{username}
</select>

完成后,再次执行已经存在的单元测试。

9. 用户-登录-业务层

(a) 规划异常

此时,应该穷举用户在“登录”过程中可能出现的任何“错误”,例如,可能出现“用户名不存在”,或“密码错误”,或“用户数据被标记为已删除”。

所以,需要为以上“错误”创建对应的异常类:

cn.tedu.store.service.ex.UserNotFoundException

cn.tedu.store.service.ex.PasswordNotMatchException

创建的异常类都应该继承自ServiceException

(b) 接口与抽象方法

IUserService接口中添加“登录”的抽象方法:

User login(String username, String password) throws UserNotFoundException, PasswordNotMatchException;

© 实现抽象方法

UserServiceImpl实现类中重写以上抽象方法:

@Override
public User login(String username, String password) throws UserNotFoundException, PasswordNotMatchException {
	// 根据参数username执行查询
	User result = userMapper.findByUsername(username);
	// 判断查询结果是否为null
	if (result == null) {
		// 是:抛出UserNotFoundException
		throw new UserNotFoundException(
			"登录失败!用户数据不存在!");
	}
	
	// 判断查询结果中的isDelete是否为1
	if (result.getIsDelete() == 1) {
		// 是:抛出UserNotFoundException
		throw new UserNotFoundException(
			"登录失败!用户数据不存在!");
	}

	// 从查询结果中获取盐值
	String salt = result.getSalt();
	// 基于参数password和盐值执行加密
	String md5Password = getMd5Password(password, salt);
	// 判断以上加密结果与查询结果中的password是否不匹配
	if (!md5Password.equals(result.getPassword())) {
		// 是:抛出PasswordNotMatchException
		throw new PasswordNotMatchException(
			"登录失败!密码错误!");
	}

	// 将查询结果中的password设置为null
	result.setPassword(null);
	// 将查询结果中的salt设置为null
	result.setSalt(null);
	// 将查询结果中的isDelete设置为null
	result.setIsDelete(null);
	// 返回查询结果
	return result;
}

最后,在UserServiceTests中编写并执行单元测试:

@Test
	public void login() {
		try {
			String username = "root";
			String password = "1234x";
			User result = service.login(username, password);
			System.err.println(result);
		} catch (ServiceException e) {
			System.err.println(e.getClass().getName());
			System.err.println(e.getMessage());
		}
	}

10. 用户-登录-控制器层

(a) 统一处理异常

(b) 设计请求

© 处理请求

11. 用户-登录-前端界面

12. 用户-修改密码-持久层

13. 用户-修改密码-业务层

14. 用户-修改密码-控制器层

15. 用户-修改密码-前端界面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
商店恢复包windowsstore_ltsc2019是指用于修复及恢复Windows操作系统中商店应用程序的工具包。Windows商店是Windows操作系统中的应用商店,在商店中用户可以下载和安装各种应用程序和游戏。然而,由于各种原因,有时商店应用程序可能会出现问题,如无法打开、崩溃或无法更新等。 商店恢复包windowsstore_ltsc2019提供了一种解决这些问题的方法。使用商店恢复包,用户可以重新安装商店应用程序,并修复其相关的文件和设置。该工具包可以通过微软官方网站或Windows系统更新中心下载和安装。 安装商店恢复包非常简单,用户只需执行几个简单的步骤即可完成。首先,用户需要访问微软官方网站或Windows系统更新中心,然后下载商店恢复包windowsstore_ltsc2019的安装程序。安装程序将自动下载并安装所需的文件。 安装完成后,用户需要运行商店恢复包windowsstore_ltsc2019的程序。该程序将自动检测并修复商店应用程序中的问题。用户可以选择是否修复或重新安装商店应用程序。 商店恢复包windowsstore_ltsc2019还提供了一些额外的功能。用户可以使用商店恢复包来清理商店应用程序的缓存、重置商店应用程序的设置,以及卸载商店应用程序等。 总之,商店恢复包windowsstore_ltsc2019是一个非常有用的工具,可以帮助用户修复和恢复Windows系统中商店应用程序的问题。它简单易用,提供了多种功能,能够使用户轻松解决商店应用程序的各种错误和故障。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员西柚柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值