日常项目中用户注册信息入库时密码要对其进行加密操作,保障用户信息安全。下面记录Spring Boot整合Spring Security进行BCrypt密码加密。
一、创建一个Spring Boot项目,需要web支持,mysql数据库,jpa和security依赖如下:
<?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 http://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.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wdg</groupId>
<artifactId>bcryptdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>bcryptdemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</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-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、application.properties配置文件:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/student?characterEncoding=UTF8
spring.datasource.username=root
spring.datasource.password=123
spring.jpa.database=mysql
spring.jpa.show-sql=true
三、加入了security的依赖,使用 @EnableWebSecurity注解,开启认证和授权,默认会拦截所有请求地址,自定义配置类,重写 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 中的
protected void configure(HttpSecurity http) {...} 方法:
package com.wdg.bcrypt.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author WDG
* @date 2019-2-16
*/
@SpringBootConfiguration
@EnableWebSecurity
public class WebMvcConfig extends WebSecurityConfigurerAdapter {
/**
* 我们在添加了spring security依赖后,所有的地址都被spring security所控制了,我们目
* 前只是需要用到BCrypt密码加密的部分,所以我们要添加一个配置类,重写方法,配置为所有地址
* 都可以匿名访问。
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//所有访问地址不被拦截,关闭scrf防卫攻击
http
.authorizeRequests()
.antMatchers("/**")
.permitAll()
.and()
.csrf().disable();
}
@Bean
public BCryptPasswordEncoder encoder (){
return new BCryptPasswordEncoder();
}
}
四、实体类:
package com.wdg.bcrypt.bean;
import javax.persistence.*;
/**
* @author WDG
* @date 2019-2-16
*/
@Entity
@Table(name="user")
public class User {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
private String email;
private String password;
private String username;
//setter and getter ...
}
五、dao:
package com.wdg.bcrypt.repository;
import com.wdg.bcrypt.bean.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author WDG
* @date 2019-2-16
*/
public interface UserReposity extends JpaRepository<User,Integer> {
/**
* 根据用户名查询用户信息
* @param username
* @return
*/
User findUserByUsername(String username);
}
六、service层:
1)、接口:
package com.wdg.bcrypt.service;
import com.wdg.bcrypt.bean.User;
/**
* @author WDG
* @date 2019-2-16
*/
public interface UserService {
/**
* 用户注册
* @param user
*/
public void addUser(User user);
/**
* 用户登录
* @param username
* @param password
* @return
*/
public User userLogin(String username,String password);
}
2)、实现:
package com.wdg.bcrypt.service.impl;
import com.wdg.bcrypt.bean.User;
import com.wdg.bcrypt.repository.UserReposity;
import com.wdg.bcrypt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
/**
* @author WDG
* @date 2019-2-16
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserReposity userReposity;
@Autowired
private BCryptPasswordEncoder encoder;
@Override
public void addUser(User user) {
//入库前进行密码加密操作
user.setPassword(encoder.encode(user.getPassword()));
userReposity.save(user);
}
@Override
public User userLogin(String username, String password) {
User user = userReposity.findUserByUsername(username);
if(user != null){
//密码验证
//第一个参数,为前台用户传入的没有加密的rawPassword,第二个为数据库中加密的encodedPassword
boolean result = encoder.matches( password,user.getPassword());
if(result){
//密码验证成功
return user;
}
}
return null;
}
}
七、控制层:
package com.wdg.bcrypt.controller;
import com.wdg.bcrypt.bean.User;
import com.wdg.bcrypt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* @author WDG
* @date 2019-2-16
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/userRegister")
public Map<String,Object> userRegister(@RequestBody User user){
Map<String,Object> map = new HashMap<String,Object>();
try {
userService.addUser(user);
map.put("result",true);
map.put("message","注册成功!");
}catch (Exception e){
e.printStackTrace();
map.put("result",false);
map.put("message","注册失败!");
}
return map;
}
@PostMapping("/userLogin")
public Map<String,Object> userLogin(@RequestBody Map<String,String> userMap){
Map<String,Object> map = new HashMap<String,Object>();
try {
User user = userService.userLogin(userMap.get("username"), userMap.get("password"));
if(user != null){
map.put("result",true);
map.put("message","登录成功!");
map.put("username",user.getUsername());
return map;
}
}catch (Exception e){
e.printStackTrace();
}
map.put("result",false);
map.put("message","登录失败,用户名或密码不正确");
return map;
}
}
八、运行启动类:
1)、postman测试,地址栏输入localhost:8080/user/userRegister
body: {
"username":"wdg",
"password":"qwer",
"email":"333"
}
运行成功后,打开数据库,新增的记录用户密码已经被加密了。
2)、登录测试:
body: {
"username":"wdg",
"password":"qwer"
}
返回结果:
密码校验成功了。