小小的项目
作者:互联网
使用Thymeleaf+SpringBoot开发用户管理系统
Spring Boot支持FreeMarker、Groovy、Thymeleaf和Mustache四种模板解析引擎,官方推荐使用Thymeleaf。
口令加密问题
口令解密存放是有必要的,可以避免廉政危机
###加密算法
- 对称加密
优点:算法公开、计算量小、加密速度快、加密效率高、可逆
缺点:双方使用相同钥匙,安全性得不到保证
算法: 在对称加密算法中常用的算法有:DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等。相较于DES和3DES算法而言,AES算法有着更高的速度和资源使用效率
- 非对称加密
需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)
非对称加密中使用的主要算法有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等
公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密
非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快
对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了
但是RSA加密算法效率较差,对大型数据加密时间很长,一般用于小数据。
- 单向加密
不能解密,最常见的算法有MD5、SHA-1等
Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护
是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。
根据输出值,不能得到原始的明文,即其过程不可逆
MD5算法具有以下特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被”压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等。
public class A {
public static void main(String[] args) throws NoSuchAlgorithmException {
String ss="123456";
MessageDigest md=MessageDigest.getInstance("MD5");//参数就是算法名称
byte[] arr=md.digest(ss.getBytes());//获取原文的数字签名值
BASE64Encoder encoder=new BASE64Encoder(); //将字节数组转换为可读的字符串
String target=encoder.encode(arr);
System.out.println(target); //4QrcOUm6Wau+VuBX8g+IPg==
System.out.println(target.length());
//md5可以采用碰撞算法解密,密文通过碰撞算法可以获取加密结果相关的一个字符串,注意不是原文串
//解决方案为加盐salt
String salt= UUID.randomUUID().toString().replace("-","");//永不重复的随机字符串
arr=md.digest((ss+salt).getBytes());
target=encoder.encode(arr);
System.out.println(target); //0QK01bYzSBmrh6YhFm9XAw==
//为了进一步提高加密效果,可以进行多次加密计算
for(int i=0;i<10;i++){
arr=md.digest((ss+salt).getBytes());
ss=encoder.encode(arr);
}
target=encoder.encode(arr);
System.out.println(target); //MXStE9GyPGGoinZ7/twIKw==
}
}
相关配置
spring:
datasource:
druid: # druid连接池的相关配置
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF8
username: root
password: 123456
sql:
init: # 数据库初始化操作的配置,当应用启动时会自动执行所指定的sql文件
schema-locations: classpath*:database/schema.sql
enabled: true
thymeleaf: # 关闭Thymeleaf缓存,一般开发时必须关闭,否则修改效果无法立即体现
cache: false
pagehelper: # 采用插件方式进行物理分页的配置
helper-dialect: mysql # 定义数据库平台
reasonable: true # 分页参数的合理化处理
惯例优于配置
- resource/static目录下存放静态资源,例如css、图片、视频等
- resource/templates目录下存放模板文件,采用html5定义模板
- Thymeleaf有额外的html标签属性
持久层
参照表结构定义对应的实体类
@Data
@Table(name="t_roles") //定义对应的表名称
public class Role implements Serializable {
@Id//用于声明标识属性---主键
@KeySql(useGeneratedKeys = true) //要求插入数据后应该返回数据表自动生成的id值
private Long id;
private String title;
}
继承框架提供的Mapper接口定义对应的Mapper接口
@Repository
public interface RoleMapper extends Mapper<Role> {
}
为了实现系统自动发现Mapper接口,并提供代理实现,所以需要在主类上添加Mapper接口的自动扫描
@MapperScan("com.yan.dao")
@SpringBootApplication
public class Springboot05Application {
public static void main(String[] args) {
SpringApplication.run(Springboot05Application.class, args);
}
}
业务层
Spring要求面向接口编程
定义接口
public interface IUserServ {
boolean createUser(User user);
}
提供实现类
@Service
public class UserServImpl implements IUserServ{
@Autowired
private UserMapper userMapper;
@Override
public boolean createUser(User user) {
int res=userMapper.insertSelective(user);
return res>0;
}
}
事务支持
在主类上添加注解,打开注解事务的支持
@EnableTransactionManagement
@SpringBootApplication
public class Springboot05Application {
public static void main(String[] args) {
SpringApplication.run(Springboot05Application.class, args);
}
}
在业务类上添加对应的事务特性说明,Spring提供5方面的特性设置
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
@Service
public class UserServImpl implements IUserServ{
@Autowired
private UserMapper userMapper;
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public boolean createUser(User user) {
int res=userMapper.insertSelective(user);
return res>0;
}
}
控制器
第一次访问应该是打开输入页
@Controller
public class UserController {
@Autowired
private IUserServ userService;
@RequestMapping(value={"","/","/add"},method = RequestMethod.GET)
public String add(Model model)throws Exception{
return "user/add";
}
}
输入页面
采用模板定义页面,所以页面的存放位置为resources/templates目录下
- 如果需要在页面种使用Thymeleaf语法,则需要引入对应的名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
####Thymeleaf相关语法
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/hello")
public String hello(@RequestParam(required = false,defaultValue = "Thymeleaf") String username, Model model){
String res="Hello "+username+"!";//模拟业务逻辑处理
model.addAttribute("msg",res);//通过request传递数据到页面
return "test";
}
}
模板定义/resources/templates/test.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--这里的th:text中使用的是一个字符串类型的字面量-->
<p th:text="'hello SpringBoot'">hello thymeleaf</p>
<!--通过表达式语言获取控制器传递的数据 -->
<div th:text="${msg}">原始显示内容</div>
</body>
</html>
如果不通过服务器直接访问,则页面会忽略所有的Thymeleaf语法,所以显示原始内容;而通过服务器访问页面时,则thymeleaf生效,会显示这行结果,即th:text中表达式的计算结果
循环操作
1、在控制器中向model中存储集合类型的数据
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/hello")
public String hello(@RequestParam(required = false,defaultValue = "Thymeleaf") String username, Model model){
List<Integer> list=new ArrayList<>();
for(int i=0;i<10;i++)
list.add(i);
model.addAttribute("list",list);
return "test";
}
}
在模板页中进行循环遍历显示
<div th:each="tt:${list}" th:text="${tt}">原始数据</div>
其中${list}
获取数据,each对获取的数据进行遍历,每次获取的元素赋值给tt,再使用text进行显示
在页面种的典型应用
<select id="roleId" name="roleId">
<option value="">请选择用户身份</option>
<option th:each="role:${roleList}" th:value="${role.id}" th:text="${role.title}" value="1">选项1</option>
</select>
遍历map的方法
<input type="radio" id="sex" name="sex" value="1" th:each="item:${sexOptions}" th:value="${item.key}" th:text="${item.value}">
客户端数据校验
可以使用jquery-validate库实现
<script src="jslib/jquery.js"></script>
<script src="jslib/jquery.validate.js"></script>
<script>
$(function(){
$('#form1').validate({ 这里的#form1对应的是输入表单<form id="form1">
rules:{ 验证规则
username:{ 输入域的名称
required:true,
rangelength:[6,20],
remote:'check'
}
},messages:{ 本地化的报错信息
username:{
required:'用户名不能空!',
rangelength:'用户名称应该在6到20个字符之间',
remote:'用户名称已占用!'
}
}
});
}
</script>
###服务器数据校验
添加依赖
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
在实体类的属性上添加验证规则
@NotBlank(groups = {UserGroup.AddFirstGroup.class},message = "用户口令不能为空")
@Length(min = 6,max = 20,groups = {UserGroup.AddSecondGroup.class},message = "用户口令应该是6到20个字符之间")
private String password;
在控制器方法上添加注解要求执行服务器端数据校验
@RequestMapping(value="/add",method = RequestMethod.POST)
public String add(@ModelAttribute("user") @Validated(UserGroup.AddGroup.class) User user, Errors errors)throws Exception{
if(errors.hasErrors())
return "user/add";
return "redirect:/login";
}
页面显示报错信息th:errors
<input type="password" id="password" name="password"/>
<span class="fieldError" th:if="${#fields.hasErrors('*{password}')}" th:errors="*{password}"></span>
标签:小小的,加密,String,项目,public,算法,class,MD5 来源: https://blog.csdn.net/lyxnb_/article/details/117566609