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