天天看點

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"
}
           

繼續閱讀