代碼地址
在上文中實現了基於內存的登錄,書接上文,這次我們用基於數據庫的方式實現登錄
使用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());
}
- 重啓項目進行測試即可