英文:
Field injection of a service in AuthenticationSuccessHandler in SpringBoot
问题
在我的应用程序中,我有一个Account
类,它还实现了UserDetails
接口。我还创建了一个名为MyAuthenticaionSuccessHandler
的类,它扩展了SimpleUrlAuthenticationSuccessHandler
类。我想要的是在用户登录后更改Account
类中的dateLastLogin
字段。在onAuthenticationSuccess
方法中,我想要一个AccountService
的实例,其中存在save(Account account)
方法,以将更新后的Account
保存到数据库中。问题开始出现在这里。我不能进行字段注入,因为我必须在构造函数中初始化AccountService
的实例。但我不能这样做,因为那样我就无法创建MyAuthenticaionSuccessHandler
的实例。我也不能手动创建它。其他类的实例,比如服务或控制器,在其中自动创建其他服务/存储库类的实例,所以在那里可以工作。但如何使它适用于自定义身份验证成功处理程序呢?
以下是您提供的代码片段:
WebSecurityConfigureAdapter类的一部分
// ...
.formLogin()
.loginPage("/guest/login")
.permitAll()
.failureHandler(new MyAuthenticationFailureHandler("/guest/login"))
.successHandler(new MyAuthenticationSuccessHandler("/user/overview"))
.and()
.logout()
// ...
AccountService类的一部分
@Service
@Transactional
public class AccountService implements UserDetailsService {
private final AccountRepository accountRepository;
private final ActivationCodeService activationCodeService;
public AccountService(AccountRepository accountRepository, ActivationCodeService activationCodeService) {
this.accountRepository = accountRepository;
this.activationCodeService = activationCodeService;
}
public void saveAccount(Account account){
accountRepository.save(account);
}
// ...
我的自定义身份验证成功处理程序
public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final AccountService accountService; // <-- 这里不起作用
public MyAuthenticationSuccessHandler() {
}
public MyAuthenticationSuccessHandler(String defaultTargetUrl) {
super(defaultTargetUrl);
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
super.onAuthenticationSuccess(request, response, authentication);
Account account = (Account)authentication.getPrincipal();
account.setDateLastLogin(new Date());
accountService.saveAccount(account);
}
}
希望这些信息对您有所帮助。如果您有任何其他问题,请随时提问。
英文:
in my app I have an Account
class which also implements UserDetails
. I also created class MyAuthenticaionSuccessHandler
which extends SimpleUrlAuthenticationSuccessHandler
. What I want is to change a field dateLastLogin
on Account
after user logs in. In method onAuthenticationSuccess
I want instance of AccountService
in which method save(Account account)
exist, to save updated Account
to db. The problem begins here. I can't do field injection, because I have to initialize an instance of AccountService
in constructor. I can't do that, because then I won't be able to create an instance of MyAuthenticaionSuccessHandler
. I also can't create it manually. Instances of other classes like services or controllers in which instances of other service/repository classes are created automatically, so there it works. But how to make it work for custom authentication success handler?<br>
Here are pieces of my code:<br>
Piece of class that extends WebSecurityConfigureAdapter
// ...
.formLogin()
.loginPage("/guest/login")
.permitAll()
.failureHandler(new MyAuthenticationFailureHandler("/guest/login"))
.successHandler(new MyAuthenticationSuccessHandler("/user/overview"))
.and()
.logout()
// ...
Piece of AccountService
@Service
@Transactional
public class AccountService implements UserDetailsService {
private final AccountRepository accountRepository;
private final ActivationCodeService activationCodeService;
public AccountService(AccountRepository accountRepository, ActivationCodeService activationCodeService) {
this.accountRepository = accountRepository;
this.activationCodeService = activationCodeService;
}
public void saveAccount(Account account){
accountRepository.save(account);
}
// ...
And my own authentication success handler
public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final AccountService accountService; // <-- here it doesn't work
public MyAuthenticationSuccessHandler() {
}
public MyAuthenticationSuccessHandler(String defaultTargetUrl) {
super(defaultTargetUrl);
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
super.onAuthenticationSuccess(request, response, authentication);
Account account = (Account)authentication.getPrincipal();
account.setDateLastLogin(new Date());
accountService.saveAccount(account);
}
}
答案1
得分: 1
在Spring应用程序中,不应直接使用new
关键字来创建对象。你可以通过使用@Bean
注解来创建一个Bean,然后使用@Autowired
注解进行自动装配。
@Configuration
public class AppConfiguration() {
@Bean
public MyAuthenticationSuccessHandler myAuthenticationSuccessHandler (){
return new MyAuthenticationSuccessHandler("/user/overview");
}
}
@Autowired
private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
英文:
You should not use new
to create an object directly in a spring application. What you can do is create a bean using @Bean
annotation and autowire it using @Autowired
annotation.
@Configuration
public class AppConfiguration() {
@Bean
public MyAuthenticationSuccessHandler myAuthenticationSuccessHandler (){
return new MyAuthenticationSuccessHandler("/user/overview");
}
}
---
@Autowired
private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
答案2
得分: 0
我在查看您的代码时并没有看到不能将 AccountService
注入到 MyAuthenticationSuccessHandler
中的任何原因。如果您发布的代码确实是您的确切代码,那么问题出在以下部分:
.successHandler(new MyAuthenticationSuccessHandler("/user/overview"))
因为在这里使用了 new
,这使得Spring完全不参与其中,因此没有将任何内容注入到 MyAuthenticationFailureHandler
中。
在您的 WebSecurityConfigureAdapter
中,尝试添加一个成员变量:
@Autowired
private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
然后,在您的链中像这样添加它:
.successHandler(myAuthenticationSuccessHandler)
如果您绝对需要在此bean构造函数中传递参数(URL),那么您将需要创建一个BeanFactory,用于生成类型为 MyAuthenticationSuccessHandler
的Spring bean,其中包含您的URL。
英文:
In looking at your code I don't see any reason why you cannot inject AccountService
into MyAuthenticationSuccessHandler
. If the code you've posted is your exact code, then the problems lies in
.successHandler(new MyAuthenticationSuccessHandler("/user/overview"))
because by using new
here, you've taken Spring completely out of the equation and aren't getting any injections into MyAuthenticationFailureHandler
.
In your WebSecurityConfigureAdapter
try adding a member variable
@Autowired
private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
then, in your chain, add it like so
.successHandler(myAuthenticationSuccessHandler)
If you absolutely must have parameters in this bean constructor (the url), then you'll need to create a BeanFactory that produces a Spring bean of type MyAuthenticationSuccessHandler
that contains your url.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论