上一篇:SpringSecurity学习一 快速开始
下一篇::SpringSecurity学习三 SpringSecurity 结合jwt
SpringSecurity部署数据库
基本的SpringSecurity部署,从数据库读取用户。
持久层框架是mybatis-plus
项目源码gitte地址: https://gitee.com/xiang_Gitee/spring-security-learn(子工程basic)
必要依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--数据相关-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
开始之前
理解SpringSecurity是完全由Filter链进行控制的,所以要根据需求定制就需要替换其中的Filter,这意味着Filter的内容掌握得好更便于学习SpringSecurity。
推荐博文Spring Security 入门原理及实战,Spring Security的一些工作原理部分解释得很好。
配置
数据库配置
- 建user表
- 建立user表的映射类
这里比较特殊的是将user表的映射类直接继承了UserDetails ,UserDetails 是SpringSecurity运行时用来存储用户信息的类,实际上也可以为UserDetails 建一个表作为用户表来用
@Data
public class User implements UserDetails {
private Integer id;
private String username;
private String password;
@TableField(exist = false)
private Boolean enabled;
@TableField(exist = false)
private String userface;
@TableField(exist = false)
private String remark;
@TableField(exist = false)
private List<Role> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
- mapper
public interface UserMapper extends BaseMapper<User> {
}
4.service
注意此service并不同于普通的service类,这里的UserService 实现了UserDetailsService ,这个接口只需要实现一个方法loadUserByUsername(String username)
,顾名思义就是根据用户名加载用户,返回值类型是UserDetails,不管是从数据库还是别的什么地方都可以在方法体里自定义了。
public class UserService implements UserDetailsService {
@Resource
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper().lambda();
lambdaQueryWrapper.eq(User::getUsername,username);
User user = userMapper.selectOne(lambdaQueryWrapper);
if (user==null){
throw new UsernameNotFoundException("用户查询失败");
}
return user;
}
}
只要把这个UserDetailsService 的实现类配置到某个位置,就可以根据在方法体的流程获取用户信息了。这个配置自然是在SecurityConfig.java里面做了。
- 配置SecurityConfig
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()//禁用跨域保护策略,默认开启
.disable()
.authorizeRequests()//认证需求路径
.antMatchers("/", "/home")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()//登录路径
.loginPage("/signin")
.loginProcessingUrl("/dosignin")
.failureUrl("/error")
.defaultSuccessUrl("/hello")
.permitAll()
.and()
.logout()//登出路径
.logoutSuccessUrl("/home")
.logoutUrl("/logout");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(NoOpPasswordEncoder.getInstance());
}
}
可以看到和上一篇文章simple相比,去掉了内存用户的配置,多了一个覆盖方法configure(AuthenticationManagerBuilder auth),参数类型AuthenticationManagerBuilder 是认证管理器,在认证管理器里去配置上一步的UserService,密码编码器为了方便仍然采用NoOpPasswordEncoder不加密,也可以换成auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
用BCrypt编码
Spring Security 中提供了 BCryptPasswordEncoder 密码编码工具,可以非常方便的实现密码的加密加盐,相同明文加密出来的结果总是不同,这样就不需要用户去额外保存盐的字段了,这一点比 Shiro 要方便很多。
运行
其他文章
SpringSecurity学习一 快速开始
SpringSecurity学习二 SpringSecurity部署数据库