天天看点

BCrypt密码加密1. BCrypt密码加密

1. BCrypt密码加密

1.1 准备工作

任何应用考虑到安全,绝不能明文的方式保存密码。密码应该通过哈希算法进行加密。有很多标准的算法比如SHA或者MD5,结合salt(盐)是一个不错的选择。 Spring Security提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用BCrypt强哈希方法来加密密码。

BCrypt强哈希方法 每次加密的结果都不一样。

(1)tensquare_user工程的pom引入依赖

<dependency>
		  <groupId>org.springframework.boot</groupId>
		  <artifactId>spring-boot-starter-security</artifactId>
	  </dependency>
           

(2)添加配置类 (资源/工具类中提供)

我们在添加了spring security依赖后,所有的地址都被spring security所控制了,我们目前只是需要用到BCrypt密码加密的部分,所以我们要添加一个配置类,配置为所有地址都可以匿名访问。

package com.tensquare.user.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;

/**
 * 安全配置类
 * 继承 WebSecurityConfigurerAdapter ,并重写它的方法来设置一些web安全的细节
 */
@Configuration
//注解开启Spring Security的功能
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
            	//通过 authorizeRequests() 定义哪些URL需要被保护、哪些不需要被保护。
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable();
    }
    
    /**
     * BCryptPasswordEncoder加密工具类
     * @return
     */
    @Bean
    public BCryptPasswordEncoder bcryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
           

3)修改tensquare_user工程的Application, 配置bean(略)

/**
     * BCryptPasswordEncoder加密工具类
     * @return
     */
    @Bean
    public BCryptPasswordEncoder bcryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
           

1.2 管理员密码加密

1.2.1 新增管理员密码加密

1)修改tensquare_user工程的AdminService

@Autowired
	private BCryptPasswordEncoder passwordEncoder;
	/**
	 * 增加
	 * @param admin
	 */
	public void saveAdmin(Admin admin) {
		admin.setId( idWorker.nextId()+"" );
		//密码加密
		admin.setPassword(passwordEncoder.encode(admin.getPassword()));
		adminRepository.save(admin);
	}
           

2)测试

POST http://localhost:9008/admin
{
  "loginname": "admin",
  "password": "123456",
  "state": "1"
}
{
  "loginname": "root",
  "password": "123456",
  "state": "1"
}
           

【提醒】同样的密码两次加密后的结果不一致。

1.2.2 管理员登陆密码校验

(1)AdminRepository增加方法定义

/**
     * 根据登录名查询返回管理员对象
     * @param loginname
     * @return
     */
    Admin findByLoginname(String loginname);
           

(2)AdminService增加方法

/**
	 * 根据登录名和密码来查询管理员对象
	 * @param loginname
	 * @param password
	 * @return
	 */
	public Admin findAdminByLoginnameAndPassword(String loginname,String password){
		
		//调用dao,根据用户名查询用户
		Admin admin = adminRepository.findByLoginname(loginname);
		//判断用户是否为空
		if(null == admin){
			//用户名不存在,则返回空
			return null;
		}
		//用户存在,判断密码是否一致
		if(passwordEncoder.matches(password,admin.getPassword())){
			//返回管理员对象
			return admin;
		}else{
			//密码不一致,也可以返回个性化的数据对象,或者抛异常
			return null;
		}
	}

           

(3)AdminController增加方法

/**
	 * 管理员登录
	 * @param loginMap
	 * @return
	 */
	@PostMapping("/login")
	public ResultDTO login(@RequestBody Map<String,String> loginMap){
		//调用业务层查询
		Admin admin =adminService.findAdminByLoginnameAndPassword(loginMap.get("loginname"),loginMap.get("password"));
		//判断
		if(null!=admin){
			//登录成功
			return new ResultDTO(true,StatusCode.OK,"登录成功");
		}else{
			//登录失败
			return new ResultDTO(false,StatusCode.LOGINERROR,"用户名或密码错误");
		}
	}
           

(4)测试

POST http://localhost:9008/admin/login
{
  "loginname": "admin",
  "password": "1234561"
}
           

1.3 用户密码加密

1.3.1 用户注册密码加密

需求:用户按照手机号码来注册

(1)修改tensquare_user工程的UserService 类,引入BCryptPasswordEncoder,修改add方法,添加密码加密的逻辑。(注意不要修改错方法)

@Autowired
	private BCryptPasswordEncoder passwordEncoder;
	/**
	 * 增加,需要验证码校验
	 * @param user
	 * @param checkcode
	 */
	public void saveUser(User user,String checkcode) {
		//1. 判断验证码是否正确
......
		//密码加密
		user.setPassword(passwordEncoder.encode(user.getPassword()));

		userRepository.save(user);
......
		//注册成功后,移除验证码
	}
           

(2)测试运行后,添加数据

暂时注释掉验证码校验的代码,进行增加新用户测试:

POST http://localhost:9008/user
{
    "mobile": "18516566522",
    "password": "123456",
    "nickname":"李老师"
}
           

1.3.2 用户登陆密码判断

(1)修改tensquare_user工程的UserRepository接口,增加方法定义

/**
     * 根据手机号查询用户
     * @param mobile
     * @return
     */
    User findByMobile(String mobile);
           

(2)修改tensquare_user工程的UserService 类,增加方法

/**
	 * 根据手机号和密码查询用户
	 * @param mobile
	 * @param password
	 * @return
	 */
	public User findUserByMobileAndPassword(String mobile,String password){
		//调用dao,根据用户名查询用户
		User user = userRepository.findByMobile(mobile);
		//判断用户是否为空
		if(null == user){
			//用户名不存在,则返回空
			return null;
		}
		//用户存在,判断密码是否一致
		if(passwordEncoder.matches(password,user.getPassword())){
			//返回用户对象
			return user;
		}else{
			//密码不一致,也可以返回个性化的数据对象,或者抛异常
			return null;
		}
	}

           

(3)修改tensquare_user工程的UserController类,增加login方法

/**
	 * 用户登录
	 * @param loginMap
	 * @return
	 */
	@PostMapping("/login")
	public ResultDTO login(@RequestBody Map<String,String> loginMap){
		//调用业务层查询
		User user=userService.findUserByMobileAndPassword(loginMap.get("mobile"),loginMap.get("password"));
		//判断
		if(null!=user){
			//登录成功
			return new ResultDTO(true,StatusCode.OK,"登录成功");
		}else{
			//登录失败
			return new ResultDTO(false,StatusCode.LOGINERROR,"用户名或密码错误");
		}
	}
	
           

(4)使用刚才新增加的账号进行测试,查看返回结果

POST http://localhost:9008/user/login
{
  "mobile": "18516566522",
  "password": "1234516"
}
           

继续阅读