前情提要:本demo是基于springboot+mybatis-plus实现加密,加密为主,全局异常处理,日志处理为辅,而登录密码加密是每个项目中必须要的,密码不可能明文存入数据,这样没有安全性。
涉及的功能,全局异常处理,日志处理,mybatis-plus实现与数据库的交互,密码加密,restful风格
涉及的工具:IDEA,postman,sqlyog(navicat)
1. 首先我们直接看效果吧,如果你不满意,也就没必要看了
如果这正是你想要的效果呢,那你可以继续看下面的内容了
2. 首先,我们看下pom.xml文件
以下依赖为所需的主要依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.jgsu</groupId> <artifactId>springboot_rsa_encryption</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot_encryption</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- WEB依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 热部署依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!-- mysql的依赖,用于连接数据库--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!-- lombok依赖,简化set/get方法 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.20</version> </dependency> <!--druid数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!--spring-security实现密码加密--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.1.6.RELEASE</version> </dependency> <!--fastjsoon--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.51</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3. 创建启动类SpringbootEncryptionApplication
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @SpringBootApplication @MapperScan("com.jgsu.mapper") public class SpringbootEncryptionApplication { public static void main(String[] args) { SpringApplication.run(SpringbootEncryptionApplication.class, args); } /** * 将加密工具类加入IOC容器中,便于加密 * */ @Bean public BCryptPasswordEncoder encoder() { return new BCryptPasswordEncoder(); } }
4.实体类
这里只有用户名和密码(其他数据自己可扩展)
@Data @AllArgsConstructor @NoArgsConstructor @TableName("user") public class User { @TableId(value = "id",type = IdType.AUTO) private int id; private String username; private String password; }
5. service层(业务层)
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.jgsu.entity.User; import com.jgsu.exception.DataAddException; import com.jgsu.exception.DataMatchException; import com.jgsu.mapper.UserMapper; import com.jgsu.service.UserService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; @Slf4j @Service public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; // 数据加密,在启动类中已经注入进IOC容器中 @Autowired private BCryptPasswordEncoder encoder; @Override public User userLogin(String username,String password) { // mybatis-plus的条件构造器,这里实现根据username查询 QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.eq("username", username); User userLogin = userMapper.selectOne(wrapper); /** * encoder.matches(password, userLogin.getPassword(),实现输入的密码与数据库中的密码进 * 行匹配,如果匹配成功则返回匹配的数据给controller层,如果失败则抛异常。 * 为什么没盐,没有解密了?因为这个已经被CryptPasswordEncoder封装好了, * 在encoder.matches()方进行解密匹配完全帮你封装好了,所以不必考虑, * 只需要将前端传入的密码与数据库中加密后的密码进行匹配就行。 * **/ if (userLogin != null && encoder.matches(password, userLogin.getPassword())) { log.info("用户{},登录成功",username); return userLogin; } else { log.error("用户名或密码错误"); throw new DataMatchException("405", "用户名或密码错误"); } } @Override public User userRegister(String username, String password) { User user = new User(); user.setId(user.getId()); user.setUsername(username); user.setPassword(encoder.encode(password)); int i = userMapper.insert(user); if (i == 1){ log.info("用户{}注册成功",username); return user; }else { log.error("服务器发生异常,注册失败"); throw new DataAddException("403","注册失败"); } } }
6. mapper层
如果不了解,可以建议去看看mybatis-plus官方文档
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.jgsu.entity.User; import org.springframework.stereotype.Repository; @Repository public interface UserMapper extends BaseMapper<User> { }
7.controller层
import com.jgsu.entity.User; import com.jgsu.service.UserService; import com.jgsu.utils.CommonResult; import com.jgsu.utils.ResultCode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { @Autowired UserService userService; // 注册,基于restful风格 @GetMapping("/register/{username}/{password}") public CommonResult register(@PathVariable("username") String username,@PathVariable("password") String password){ User user = userService.userRegister(username, password); if (user != null){ return CommonResult.success(ResultCode.SUCCESS); }else { return CommonResult.failed(ResultCode.FAILED); } } // 登录,基于restful风格 @GetMapping("/login/{username}/{password}") public CommonResult login(@PathVariable("username") String username,@PathVariable("password") String password) { User userLogin = userService.userLogin(username,password); if (userLogin != null) { return CommonResult.success(ResultCode.SUCCESS); } else { return CommonResult.failed(ResultCode.USERNAME_OR_PASSWORD_ERROR); } } }
8.配置类(返回json数据的类)
封装错误码的接口
public interface IErrorCode { long getState(); String getMessage(); }
枚举了一些常用API操作码
public enum ResultCode implements IErrorCode { /** * 成功 */ SUCCESS(200, "ok"), /** * 失败 */ FAILED(500, "server error"), /** * 验证过期 */ VALIDATE_FAILED(404, "undefined"), /** * 未登录 */ UNAUTHORIZED(401, "未登录"), /** * 用户名或密码错误 */ USERNAME_OR_PASSWORD_ERROR(405, "用户名或密码错误"), /** * 数据查询错误 */ DATA_Not_Exist_ERROR(603, "数据不存在"), /** * 数据添加出现问题 */ DATA_ADD_ERROR(604, "数据添加异常"), /** * 文件 */ FILE_ERROR(605, "上传文件出现错误"), /** * 数据查询出现问题 */ IMAGE_ERROR(606, "图片处理出现错误"), /** * 权限不够 */ FORBIDDEN(403, "forbidden"); private long state; private String stateInfo; ResultCode(long state, String stateInfo) { this.state = state; this.stateInfo = stateInfo; } @Override public long getState() { return state; } @Override public String getMessage() { return stateInfo; } }
通用返回对象
public class CommonResult<T> { private long state; private String stateInfo; private T data; public CommonResult() { } public CommonResult(long state, String stateInfo, T data) { this.state = state; this.stateInfo = stateInfo; this.data = data; } public CommonResult(long state, String stateInfo) { this.state = state; this.stateInfo = stateInfo; } /** * 成功返回结果 * * @param data 获取的数据 */ public static <T> CommonResult<T> success(T data) { return new CommonResult<T>(ResultCode.SUCCESS.getState(), ResultCode.SUCCESS.getMessage(), data); } /** * 成功返回结果 * @param data 获取的数据 * @param message 提示信息 * @return */ public static <T> CommonResult<T> success(T data, String message) { return new CommonResult<T>(ResultCode.SUCCESS.getState(), message, data); } /** * 失败返回结果 * @param errorCode 错误码 */ public static <T> CommonResult<T> failed(IErrorCode errorCode) { return new CommonResult<T>(errorCode.getState(), errorCode.getMessage(), null); } /** * 失败返回结果 * @param message 提示信息 */ public static <T> CommonResult<T> failed(String message) { return new CommonResult<T>(ResultCode.FAILED.getState(), message, null); } /** * 失败返回结果 * @param code * @param message */ public static <T> CommonResult<T> failed(int code, String message) { return failed(ResultCode.FAILED); } /** * 参数验证失败返回结果 */ public static <T> CommonResult<T> validateFailed() { return failed(ResultCode.VALIDATE_FAILED); } /** * 参数验证失败返回结果 * @param message 提示信息 */ public static <T> CommonResult<T> validateFailed(String message) { return new CommonResult<T>(ResultCode.VALIDATE_FAILED.getState(), message, null); } /** * 未登录返回结果 */ public static <T> CommonResult<T> unauthorized(T data) { return new CommonResult<T>(ResultCode.UNAUTHORIZED.getState(), ResultCode.UNAUTHORIZED.getMessage(), data); } /** * 未授权返回结果 */ public static <T> CommonResult<T> forbidden(T data) { return new CommonResult<T>(ResultCode.FORBIDDEN.getState(), ResultCode.FORBIDDEN.getMessage(), data); } public long getState() { return state; } public void setState(long state) { this.state = state; } public String getStateInfo() { return stateInfo; } public void setStateInfo(String stateInfo) { this.stateInfo = stateInfo; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
9. 异常类
全局异常拦截类
@Slf4j @ControllerAdvice @ResponseBody public class GlobalExceptionHander { @ExceptionHandler(value = Exception.class) public CommonResult handlerException(Exception e){ if (e instanceof DataAddException){ log.error("【全局异常拦截】DataAddException: 请求方法 {}, 请求路径 {}",((DataAddException)e).getCode(),((DataAddException)e).getMessage()); return CommonResult.failed(ResultCode.DATA_ADD_ERROR); }else if (e instanceof DataMatchException){ log.error("【全局异常拦截】DataMatchException: 请求方法 {}, 请求路径 {}",((DataMatchException)e).getCode(),((DataMatchException)e).getMessage()); return CommonResult.failed(ResultCode.USERNAME_OR_PASSWORD_ERROR); } else { log.error("服务器内部出错{}",e); return CommonResult.failed(ResultCode.FAILED); } } }
自定义数据添加异常类
public class DataAddException extends RuntimeException { private String code; private String message; public DataAddException(String code, String message) { this.code = code; this.message = message; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } @Override public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
自定义数据匹配异常类
public class DataMatchException extends RuntimeException { private String code; private String message; public DataMatchException(String code, String message) { this.code = code; this.message = message; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } @Override public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
以上是实现该功能的所有类,当然进行密码加密处理的类只涉及service层以及启动类,其他类为基本类,如果你只想了解怎么进行加密处理存入数据库以及怎么登陆就看看service层就行。
总结
到此这篇关于springboot实现注册的加密与登录的解密功能的文章就介绍到这了,更多相关springboot实现注册的加密与登录的解密内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
本文向大家介绍Spring+MongoDB实现登录注册功能,包括了Spring+MongoDB实现登录注册功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Spring,Spring MVC,MongoDB实现登录注册 的具体代码,供大家参考,具体内容如下 工程目录: Spring配置文件: Web.xml: Model层: UserDao: UserDaoImpl: Login
本文向大家介绍redis+php实现微博(一)注册与登录功能详解,包括了redis+php实现微博(一)注册与登录功能详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了redis+php实现微博注册与登录功能。分享给大家供大家参考,具体如下: (一)、微博功能概况 微博用户账号注册 微博用户登录 微博发布 添加微博好友(粉丝) 微博推送 微博冷数据写入mysql数据库 (二)、redis
本文向大家介绍C语言实现加密解密功能,包括了C语言实现加密解密功能的使用技巧和注意事项,需要的朋友参考一下 加密主要是通过一种算法对原内容进行处理,使原来内容不直观可见。解密过程通常要知道加密的算法,然后对加密后的内容进行逆处理,从而实现解密功能。当然解密也有一些暴力破解的方法。接下来以 c 语言 为例讲解一种简单的加密解密以及暴力破解字符串的方法,带您走进加密解密技术的大门。 先讲一下凯撒加密,
本文向大家介绍Android实现登录注册功能封装,包括了Android实现登录注册功能封装的使用技巧和注意事项,需要的朋友参考一下 我们都知道Android应用软件基本上都会用到登录注册功能,那么对一个一个好的登录注册模块进行封装就势在必行了。这里给大家介绍一下我的第一个项目中所用到的登录注册功能的,已经对其进行封装,希望能对大家有帮助,如果有什么错误或者改进的话希望各位可以指出。 我们都知道登录
本文向大家介绍Spring MVC+mybatis实现注册登录功能,包括了Spring MVC+mybatis实现注册登录功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Spring MVC mybatis实现注册登录功能的具体代码,供大家参考,具体内容如下 前期准备: 如下图所示,准备好所需要的包 新建工程,导入所需要的包,在web.xml中配置好所需要的,如下 配置好如
本文向大家介绍koa2 用户注册、登录校验与加盐加密的实现方法,包括了koa2 用户注册、登录校验与加盐加密的实现方法的使用技巧和注意事项,需要的朋友参考一下 加密与解密 先介绍一下关于服务端用户名跟密码的存储状态,我们知道当前端在注册一个新用户时,会在表单内填入用户名和密码,并通过post请求提交到服务器,服务器再把用户名和密码从ctx.request.body中拿出来,存入到数据库的一张表里