任何应用考虑到安全,绝不能明文的方式保存密码。密码应该通过哈希算法进行加密。有很多标准的算法比如SHA或者MD5,结合salt(盐)是一个不错的选择. Spring Security 提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用BCrypt强哈希方法来加密密码。
BCrypt强哈希方法 每次加密的结果都不一样。
(1)maven工程的pom引入依赖
org.springframework.boot
spring-boot-starter-security
(2)添加配置类
我们在添加了spring security依赖后,所有的地址都被spring security所控制了,我们目前只是需要用到BCrypt密码加密的部分,所以我们要添加一个配置类,配置为所有地址都可以匿名访问。
@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)修改maven工程的Application, 配置bean
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
@Bean
public IdWorker idWorkker(){
return new IdWorker(1, 1);
}
@Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
//Spring Security
//提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用 //BCrypt强
哈希方法来加密密码。
密码加密
maven工程的AdminService
//Spring Security
//提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用BCrypt强
//哈希方法来加密密码。
@Autowired
private BCryptPasswordEncoder encoder;/**
* 增加
* @param admin
*/
public void add(Admin admin) {
admin.setId( idWorker.nextId()+"" );//主键值
//密码加密
admin.setPassword(encoder.encode(admin.getPassword()));
adminDao.save(admin);
}
登陆密码校验
(1)AdminDao增加方法定义
public interface AdminDao extends JpaRepository,JpaSpecificationExecutor{
//通过命名规则生成sql语句
public Admin findByLoginname(String loginname);
}
(2)AdminService增加方法
@Autowired
private AdminDao adminDao;
@Autowired
private IdWorker idWorker;
//Spring Security
//提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用BCrypt强
//哈希方法来加密密码。
@Autowired
private BCryptPasswordEncoder encoder;
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,"登录失败");
}
return new Result(true,StatusCode.OK,"登录成功");
//登录的目的就是让前端和后端能通话
}
(4) 通过api测试
用户注册的密码加密和登录
修改service层的发送手机验证码方法public void sendSms(String mobile) {
//生成六位数字随机数
String checkcode = RandomStringUtils.randomNumeric(6);
//向缓存中放一份
redisTemplate.opsForValue().set("checkcode_"+mobile,checkcode,6, TimeUnit.HOURS);
//给用户发一份
Map map = new HashMap<>();
map.put("mobile",mobile);
map.put("checkcode",checkcode);
//rabbitTemplate.convertAndSend("sms",map); 注释掉这一行,不发送手机验证码,方面测试,只看控制台输入的验证码就可以
//在控制台显示一份,方便测试
System.out.println("验证码:"+checkcode);
}
修改maven工程的UserService 类的add方法,添加密码加密的逻辑
/**
* 增加
* @param user
*/
public void add(User user) {
user.setId( idWorker.nextId()+"" );
//密码加密
user.setPassword(encoder.encode(user.getPassword()));
user.setFollowcount(0);//关注数
user.setFanscount(0);//粉丝数
user.setOnline(0L);//在线时长
user.setRegdate(new Date());//注册日期
user.setUpdatedate(new Date());//更新日期
user.setLastdate(new Date());//最后登陆日期
userDao.save(user);
}
Controller层用户注册
/**
* 发送短信验证码
*/
@RequestMapping(value = "/sendsms/{mobile}",method =RequestMethod.POST )
public Result sendSms(@PathVariable String mobile){
userService.sendSms(mobile);
return new Result(true,StatusCode.OK,"发送成功");
}
/**
* 用户注册
* @return
*/
@RequestMapping(value = "/register/{code}",method =RequestMethod.POST )
public Result regist(@PathVariable String code,@RequestBody User user){
//得到缓存中的验证码
String checkcodeRedis = (String) redisTemplate.opsForValue().get("checkcode_"+user.getMobile());
if(checkcodeRedis.isEmpty()){
return new Result(false, StatusCode.ERROR, "请先获取手机验证码");
}
if(!checkcodeRedis.equals(code)){
return new Result(false, StatusCode.ERROR, "请输入正确的验证码");
}
userService.add(user);
return new Result(true,StatusCode.OK,"注册成功");
}
测试运行后,添加数据 { "mobile": "13901238899" "password": "123123", }
数据库中的密码为以下形式 $2a$10$a/EYRjdKwQ6zjr0/HJ6RR.rcA1dwv1ys7Uso1xShUaBWlIWTyJl5S
用户登陆密码判断
(1)修改maven工程的UserDao接口,增加方法定义
public interface UserDao extends JpaRepository,JpaSpecificationExecutor{
public User findByMobile(String mobile);
}
(2)修改mavenr工程的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;
}
修改maven工程的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,"登录失败");
}
return new Result(true,StatusCode.OK,"登录成功");
}
使用刚才新增加的账号进行测试,查看返回结果 进入api先获取验证码,再注册用户,再登录