SpringSecurity详细解读与应用

一、应用场景

SpringSecurity又称安全框架,拥有基于用户的 [认证] 和 [权限] 授予两大功能;

1.用户认证:验证该用户是否为数据库中存储的数据

2.权限授予:对于不同的用户给予不同访问权限,给出对于项目中不同功能/视图的是否可访问。 (视频教程地址:https://www.bilibili.com/video/BV1mm4y1X7Hc?p=1)

二、代码实现-用户认证

原生的Security框架在项目启动后,发送任意的请求,都会调用用户认证API(即输入username和password),我们可以根据自己的业务需求来修改这部分API,使Security框架可以更个性化的使用,满足我们自己的业务需求。

1.用户认证的基本逻辑👇:

整理了一份面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题

需要全套面试笔记的【点击此处即可】即可免费获取

scss

复制代码

(1)在登陆时输入校验信息(数据库字段,通常为username和password)并确认 (2)将输入信息和数据库的数据进行校验,对比一致,则根据输入的username和password生成一段基于token (3)将此token存入redis数据库:key为username,value经过mybatis查询保存为username对应的数据库记录 (4)将此token响应给前端;之后每一次请求都必须携带这个token来获取用户信息,来判断他是否有权限获得响应数据

图片.png

2.使用Security加持的代码实现👇: 

图片.png

 通常,我们习惯于将原生的用户认证修改为基于数据库字段的(例如username和password)进行登录校验的业务逻辑,这就需要我们进入Secuirty的认证流程中,修改源代码来解决。

(1)UserDetailsService接口的‘loadUserByUsername’方法:

该方法的携带了输入的username作为参数,执行数据库字段校验的逻辑可以在这里定制。

我们可以在工程中编写一个类来实现这个UserDetailsService接口的,并重写loadUserByUsername方法,制定数据库验证的业务逻辑👇

 

scss

复制代码

@Service public class MyUserDetailsServiceImpl implements UserDetailsService { @Autowired UserMapper userMapper; @Autowired UserService userService; /** * 对用户的输入进行数据库验证 * loadUserByUsername 获取用户输入的username并返回UserDetails * @param userName 来自用户输入的user在浏览器输入的user_name */ @Override public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper(); queryWrapper.eq(User::getUserName,userName); User user = userMapper.selectOne(queryWrapper); System.out.println("user:"); System.out.println(user); if (Objects.isNull(user)){ throw new RuntimeException("用户名或密码错误"); } LoginUserDetails loginUser = new LoginUserDetails(); loginUser.setUser(user); return loginUser; //不可返回空,定义LoginUser类来返回此类型的值 } }

需要注意的是,该方法返回的不是验证数据库的实体类对象,而是“UserDetails”对象,这是一个包裹了实体类验证信息的接口,我们可以通过新建一个继承UserDetails接口的类,把实体类包裹在里面,进行返回。

 

typescript

复制代码

/** * 定义一个类来返回 MyUserDetailsServiceImpl 的返回值 */ @Data @NoArgsConstructor @AllArgsConstructor public class LoginUserDetails implements UserDetails { private User user; /* 返回用户的password*/ @Override public String getPassword() { return user.getPassword(); } /* 返回用户的user_name*/ @Override public String getUsername() { return user.getUserName(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } /** * 需要返回的权限信息,与用户认证无关 */ @Override public Collection<? extends GrantedAuthority> getAuthorities() { return null; } }

至此,loadUserByUsername方法返回用户数据库数据部分结束。

(2)修改密码校验--PasswordEncode

执行完loadUserByUsername后会返回数据库的用户密码,此信息会经过PasswordEncode类,和用户输入的密码来进行校验,但是原生的PasswordEncode比较糟糕(略),所以我们在配置中修改一下PasswordEncode的校验方式,使用 BCrypt。👇 

cedf7b28add62bb0802b64c381cdfa5.png

 注意,使用此方法进行密码校验的前提是:数据库的密码必须是使用BCrypt生成的加密字符串,而不是明文。👇

 

scala

复制代码

@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { /** 根据流程,loadUserByUsername携带用户数据库信息来到PasswordEncoder,编写此配置 类的Bean,PasswordEncoder返回值修改为BCryptPasswordEncoder,即可解决loadUserByUsername 方法返回的UserDetails对象不能校验明文密码的问题了哦。 */ @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }

PasswordEncoder校验两方密码的原理 (用户在前端输入的明文,和数据库的密文,可以在BCryptPasswordEncoder使用matchs方法来校验:是否为一个同字符串的明和密两种模式) 👇

 

ini

复制代码

@Test public void BCryptPasswordEncoderTest(){ BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encode1 = passwordEncoder.encode("111111"); System.out.println(encode1); boolean matches1 = passwordEncoder.matches("111111",encode1); System.out.println(matches1); } ↓ 控制台打印 ↓ $2a$10$8I0lzvZqR4c6/hf8PP.bkuiW//N4cFlE9xuoPAyS9lelELw0WuSGG true

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值