从零蛋开始集成Spring Security 5 (三)

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。

承接上文

3.4 实现UserDetailsService

实现UserDetails, 创建了自己的用户类后, 还需要实现UserDetailsService, 将用户信息从数据库中查询出来

UserDetails相同, 先来看一下官方文档:

3-4-1 UserDtails官方文档.png

只有一个根据用户名查询用户的方法, 实现起来并不困难

笔者使用的是MyBatis, 先创建查询仓库接口UserRepository:

1
2
3
4
5
6
7
8
9
10
11
java复制代码public interface UserRepository {

 /**
  * 根据用户名查询用户信息
  *
  * @param username 用户名
  * @return 用户实体
  */
 User loadUserByUsername(@Param("username") String username);

}

具体的查询语句需要根据实际使用的数据库编写

需要注意的是, user结果中的角色属性roles应包含其对应的权限属性permissions, permissions中又应包含接口属性apis

创建用户服务类UserService:

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码@Component
@Data
@AllArgsConstructor
public class UserService implements UserDetailsService {

 private final UserRepository repository;

 @Override
 public UserDetail loadUserByUsername(String username) throws UsernameNotFoundException {
   return repository.loadUserByUsername(username);
}

}

3.5 Spring Security 5 配置

只剩下最后一步, 把刚才手动实现的内容进行配置, 告诉Spring Security就好啦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
java复制代码public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

 private final UserDetailRepository userDetailRepository;

 @Override
 protected void configure(HttpSecurity http) throws Exception {
   http.csrf().disable()
    .authorizeRequests().anyRequest().authenticated()
    .and()
    .formLogin();
}

 @Override
 @Bean
 @ConditionalOnMissingBean
 public UserDetailsService userDetailsServiceBean() {
   return new UserDetailsServiceImpl(userDetailRepository);
}

}

authenticated开启接口权限校验, formLogin开启默认表单登录

这里有个小坑, 我们需要手动配置一下PasswordEncoder:

1
2
3
4
5
6
7
8
9
10
java复制代码public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

 // 其它配置...

 @Bean
 public PasswordEncoder passwordEncoder() {
   return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

}

至此为止, 所有的Spring Security集成已经完成, 增加个测试用例ExampleApi:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码@RestController
@RequestMapping(value = "/api/v1/example")
public interface ExampleApi {

 /**
  * 分页查询
  *
  * @param parameters 查询条件
  * @param pageable   分页
  * @return 分页结果
  */
 @GetMapping(value = "")
 @PreAuthorize("hasAuthority('api:example:search')")
 RestDataResult<Page<Example>> search(SearchParameter parameters, Pageable pageable);
   
}

利用@PreAuthorize注解声明接口权限校验规则, 例如上述代码中, 访问/api/v1/example需要用户拥有api:example:search权限

4 问题

本文所完成的登录认证存在如下两个问题:

  1. 使用Spring Security默认登录页面, 丑
  2. 有状态登录, 关闭浏览器或重启应用后, 登录状态将失效, 需要重新登录

笔者将会在下篇文章中继续集成Spring Security, 引入Jwt, 实现无状态模式登录

5 拓展阅读

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%