密码加密与微服务鉴权JWT-BCrypt密码加密
BCrypt密码加密
准备工作
任何应用考虑到安全,绝不能明文的方式保存密码。密码应该通过哈希算法进行加密。
有很多标准的算法比如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.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;
/**
* 安全配置类
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
//authorizeRequests所有security全注解配置实现的开端,表示开始说明需要的权限。
//需要的权限分两部分,第一部分是拦截的路径,第二部分访问该路径需要的权限。
//antMatchers表示拦截什么路径,permitAll任何权限都可以访问,直接放行所有。
//anyRequest()任何的请求,authenticated认证后才能访问
//.and().csrf().disable();固定写法,表示使csrf拦截失效。
http
.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
}
(3)修改tensquare_user工程的Application, 配置bean
@Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
管理员密码加密
新增管理员密码加密
修改tensquare_user工程的AdminService
/**
* 增加
* @param admin
*/
public void add(Admin admin) {
admin.setId( idWorker.nextId()+"" );
// 密码加密
String newpassword = encoder.encode(admin.getPassword()); // 加密后的密码
admin.setPassword(newpassword); // 密码加密
adminDao.save(admin);
}
管理员登陆密码校验
(1)AdminDao增加方法定义
package com.tensquare.user.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import com.tensquare.user.pojo.Admin;
/**
* 数据访问接口
* @author Administrator
*/
public interface AdminDao extends JpaRepository<Admin,String>,JpaSpecificationExecutor<Admin>{
public Admin findByLoginname(String loginname);
}
(2)AdminService增加方法
public Admin login(Admin admin) {
//先根据用户名查询对象。
Admin adminLogin = adminDao.findByLoginname(admin.getLoginname());
//然后拿数据库中的密码和用户输入的密码匹配是否相同。
if(adminLogin!=null && encoder.matches(admin.getPassword(), adminLogin.getPassword())){
//保证数据库中的对象中的密码和用户输入的密码是一致的。登录成功
return adminLogin;
}
//登录失败
return null;
}
(3)AdminController增加方法
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Result login(@RequestBody Admin admin){
Admin adminLogin = adminService.login(admin);
if(adminLogin==null){
return new Result(false, StatusCode.LOGINERROR, "登录失败");
}
//使得前后端可以通话的操作。采用JWT来实现。
//生成令牌
String token = jwtUtil.createJWT(adminLogin.getId(), adminLogin.getLoginname(), "admin");
Map<String, Object> map = new HashMap<>();
map.put("token", token);
map.put("role", "admin");
return new Result(true, StatusCode.OK, "登录成功", map);
}
用户密码加密
用户注册密码加密
(1)修改tensquare_user工程的UserService 类,引入BCryptPasswordEncoder
@Autowired
private BCryptPasswordEncoder encoder;
(2)修改tensquare_user工程的UserService 类的add方法,添加密码加密的逻辑
/**
* 增加
* @param user 用户
* @param code 用户填写的验证码
*/
public void add(User user,String code) {
//判断验证码是否正确
String syscode = (String)redisTemplate.opsForValue().get("smscode_" + user.getMobile());
//提取系统正确的验证码
if(syscode==null){
throw new RuntimeException("请点击获取短信验证码");
}
if(!syscode.equals(code)){
throw new RuntimeException("验证码输入不正确");
}
user.setId( idWorker.nextId()+"" );
user.setFollowcount(0);//关注数
user.setFanscount(0);//粉丝数
user.setOnline(0L);//在线时长
user.setRegdate(new Date());//注册日期
user.setUpdatedate(new Date());//更新日期
user.setLastdate(new Date());//最后登陆日期
userDao.save(user);
}
(3)测试运行后,添加数据
{
"mobile": "13901238899"
"password": "123123",
}
数据库中的密码为以下形式
$2a$10$a/EYRjdKwQ6zjr0/HJ6RR.rcA1dwv1ys7Uso1xShUaBWlIWTyJl5S
用户登陆密码判断
(1)修改tensquare_user工程的UserDao接口,增加方法定义
public User findByMobile(String mobile);
(2)修改tensquare_user工程的UserService 类,增加方法
public User login(String mobile, String password) {
User user = userDao.findByMobile(mobile);
if(user!=null && encoder.matches(password, user.getPassword())){
return user;
}
return null;
}
(3)修改tensquare_user工程的UserController类,增加login方法
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Result login(@RequestBody User user){
user = userService.login(user.getMobile(), user.getPassword());
if(user==null){
return new Result(false, StatusCode.LOGINERROR, "登录失败");
}
String token = jwtUtil.createJWT(user.getId(), user.getMobile(), "user");
Map<String, Object> map = new HashMap<>();
map.put("token", token);
map.put("roles", "user");
return new Result(true, StatusCode.OK, "登录成功", map);
}
(4)使用刚才新增加的账号进行测试,查看返回结果