java - AuthenticationManager 的扩展点
问题描述
我正在使用 Spring Security 进行简单的登录:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebAuthenticationConfig extends WebSecurityConfigurerAdapter {
private final PasswordEncoder passwordEncoder;
private final UserDetailServiceImpl userDetailsService;
@Autowired
public WebAuthenticationConfig(PasswordEncoder passwordEncoder, UserDetailServiceImpl userDetailsService) {
this.passwordEncoder = passwordEncoder;
this.userDetailsService = userDetailsService;
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
.csrf()
.disable()
.authorizeRequests()
.antMatchers(
"/register/*",
"/login").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
如您所见,我使用的是默认 AuthManager。现在UserDetailServiceImpl
很简单:
@Service
public class UserDetailServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public UserDetailServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<UserEntity> dbUser = userRepository.findUserByEmail(email);
if (!dbUser.isPresent()) {
throw new UsernameNotFoundException("No user found with email " + email);
}
UserEntity user = dbUser.get();
return UserDetailsImpl.build(user);
}
}
在我的控制器中,我使用它,例如:
@RequestMapping(value = "login", method = RequestMethod.POST)
public void loginUser(@Valid @RequestBody LoginUserRequest request, HttpServletRequest httpServletRequest) {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getEmail(), request.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
这工作得很好,身份验证管理器调用getUserByEmail
,UserDetailServiceImpl
找到用户,然后 authenticationManager 比较密码并返回身份验证对象。
但是,如果我想在此过程中进行其他操作怎么办?如果我想记录被登录用户的 IP 地址怎么办?
我可以从控制器中提取 IP 地址,但是我实际上可以插入此功能HttpServletRequest
的扩展点在哪里?AuthenticationManager
我可以扩展AbstractAuthenticationToken
以接受有关令牌的详细信息(所以在我的情况下,除了电子邮件和密码之外,我还会通过 IP 地址进行身份验证)。
然后我可以实现我自己的AuthenticationManager
,所以它不需要我的实现UserDetailService
,因此我的AuthenticationManager
看起来像:
public class MyAuthenticationManager implements AuthenticationManager{
@Autowired
private final UserRepository;
@Autowired
private final PasswordEncoder passwordEncoder;
Authentication authenticate(Authentication authentication) throws AuthenticationException{
MyAuthToken token = (MyAuthToken) authentication;
UserEntity user = userRepository.findUserByEmail(token.getName);
// check if user exists and if password matches
userRepository.addIp(token.getIP());
}
}
但是我会失去整个身份验证管理器流程,我不确定它是否好,因为它看起来很健壮。
是否有任何扩展点可以插入我的功能?
感谢帮助
解决方案
推荐阅读
- laravel - Laravel - 从 8 个单独的表单中收集数据
- hyperledger-fabric - 对注册 ID、从属关系和属性进行 Hyperlefger 结构验证
- mysql - 如何在角度 9 中为每个类别加载子类别
- c - 有没有办法检查数组中的点是否存在
- python - 如何在python中以任何方向对多个元组列表进行排序?
- python - VSC 无法随机识别“Python 交互”会话中的 ctrl+c
- spring-boot - Thymeleaf 具有相同名称的多个输入标签
- java - 使用 Google Maps API 在 Android 中查找设备当前位置的纬度和经度值
- php - 如何使用帖子上的简码调用帖子对象(产品)自定义字段
- ios - Flutter 无法在 vscode 2020 上构建 iOS