代码地址
在上文中实现了基于内存的登录,书接上文,这次我们用基于数据库的方式实现登录
使用SpringSecurity默认提供的
- 创建数据库即对应的表,在
application.properties
配置好数据源
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`enabled` tinyint(255) NOT NULL,
PRIMARY KEY (`username`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `authorities`;
CREATE TABLE `authorities` (
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`authority` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
UNIQUE INDEX `ix_auth_username`(`username`, `authority`) USING BTREE,
CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `users` (`username`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
- 修改
WebSecurityConfig
@Autowired
private DataSource dataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
// inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser("user")
.password(passwordEncoder().
encode("123")).roles("USER")
.and()
.withUser("admin")
.password(passwordEncoder().
encode("123")).roles("ADMIN");
}
重启项目,访问请求进行测试即可;在启动的过程中就会将配置的用户插入到上面创建的表中
使用自定义的登录逻辑处理
正常情况下我们系统的用户相关表是由我们自己设计,登录逻辑有我们自己的处理。我们只需要创建类重写UserDetailsService
的loadUserByUsername
方法并将其注入到Spring容器中,再进行配置即可。
- 为了和上面的做区别,单独再创建一个
users
表
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` bigint(20) NOT NULL,
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`password` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`enable` tinyint(4) NOT NULL DEFAULT 1,
`roles` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
- 创建对应的user实体类,需要实现
UserDetails
@Data
// 表名
@TableName("users")
public class User implements UserDetails {
// id自增长
@TableId(type= IdType.AUTO)
private Long id;
private String username;
private String password;
private String roles;
private boolean enable;
// 不与数据库字段对应
@TableField(exist = false)
private List<GrantedAuthority> authorities; // 权限列表
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return this.enable;
}
}
- 我使用的MybatisPlus来与数据库交互,可以根据实际情况,实现根据用户名查询到用户信息即可
- 创建自己的
UserDetailService
,重写loadUserByUsername
方法,返回自己创建的User对象
@Service
public class MyUserDetailService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",username);
// 根据用户名查询用户
User user = userMapper.selectOne(queryWrapper);
if(null == user){
throw new UsernameNotFoundException("user not exist");
}
// Roles是String格式用逗号隔开,该工具将Role拆分成数组,并将其设置进User对象中
user.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRoles()));
return user;
}
}
- 在表中插入用户数据,注意密码需要自己手动进行加密
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode("123");
System.out.println(password);
6. 在WebSecurityConfig
中添加自己的UserDetailService
@Autowired
private MyUserDetailService userDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.jdbcAuthentication().dataSource(dataSource)
// // inMemoryAuthentication()
// .passwordEncoder(passwordEncoder())
// .withUser("user")
// .password(passwordEncoder().
// encode("123")).roles("USER")
// .and()
// .withUser("admin")
// .password(passwordEncoder().
// encode("123")).roles("ADMIN");
auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
}
- 重启项目进行测试即可