本次操作是基于SpringBoot项目的,使用Mybatis-Plus作为ORM框架,具体创建流程不再一一阐述。
org.springframework.boot spring-boot-starter-security
CREATE TABLE `users` ( `uid` int NOT NULL AUTO_INCREMENT, `username` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL, `password` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL, `phone` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL, PRIMARY KEY (`uid`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;
@Data public class Users { private Integer id; private String username; private String password; private String phone; }
public interface UsersMapper extends BaseMapper{ }
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.lion.mysecuritydemo.mapper") public class MysecuritydemoApplication { public static void main(String[] args) { SpringApplication.run(MysecuritydemoApplication.class, args); } }
在项目中,认证逻辑一般是通过自定义实现的,将实现了UserDetailsService 接口的实现类放入Spring容器中,即可实现自定义逻辑认证。
实现UserDetailsService接口必须重写 loadUserByUsername方法,该方法定义了具体的认证逻辑,参数 username 是前端传来的用户名,我们需要根据传来的用户名查询到该用户(一般是从数据库查询),并将查询到的用户封装成一个UserDetails对象,该对象是Spring Security提供的用户对象,包含用户名、密码、权限。Spring Security会根据UserDetails对象中的密码和客户端提供密码进行比较。相同则认证通过,不相同则认证失败,详细流程如下图:
数据库认证是最常用的,我们现在来看看数据库认证应该怎么写?
其实就是按我们上面说的自定义一个MyUserDetailsService类,并且实现UserDetailsService接口,将其放入Spring容器中,如下:
@Service public class MyUserDetailService implements UserDetailsService { @Autowired private UsersMapper usersDao; /** * 自定义认证逻辑(现在是数据库认证) * @param username * @return * @throws UsernameNotFoundException */ @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1. 查询用户 QueryWrapperwrapper = new QueryWrapper ().eq("username", username); Users users = usersDao.selectOne(wrapper); if (users == null){ return null; } // 2. 封装成UserDetails对象 UserDetails userDetails = User.withUsername(users.getUsername()) .password(users.getPassword()) .authorities("admin") //授权操作 .build(); return userDetails; } }
在实际开发中,为了数据安全性,在数据库中存放密码时不会存放原密码,而是会存放加密后的密码。而用户传入的参数是明文密
码。此时必须使用密码解析器才能将加密密码与明文密码做比对。Spring Security中的密码解析器是 PasswordEncoder 。
Spring Security要求容器中必须有 PasswordEncoder 实例,Spring Security官方推荐的密码解析器是 BCryptPasswordEncoder 。
我们在security配置类中加入如下一个方法即可:
@Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); }
虽然Spring Security给我们提供了登录页面,但在实际项目中,更多的是使用自己的登录页面。Spring Security也支持用户自定义登
录页面。用法如下:
登录