简体   繁体   English

如何从 Spring MVC\\Boot Controller 方法中正确检索登录的用户信息?

[英]How to correctly retrieve the logged user information from a Spring MVC\Boot Controller method?

I am pretty new in Spring Security and I have the following problem.我是Spring Security 的新手,我有以下问题。

I am working on a Spring Boot prject using Spring Security to protect all the resources into /Extranet/ ".我正在使用Spring Security开发一个Spring Boot项目,以保护所有资源进入/Extranet/ ”。

So basically my WebSecurityConfig configuration class contains this code:所以基本上我的WebSecurityConfig配置类包含以下代码:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = CustomUserDetailsService.class)
@EnableAutoConfiguration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired 
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/Extranet/**").access("hasRole('ROLE_USER')")
            .anyRequest().permitAll()
            .and()
            .httpBasic()
            .and()
            .csrf().disable();
    }
}

It works fine, infact to access to a resource as /Extranet/login I have to set the Basic Authentication and specify the correct username and password (performing the request using Postman tool to test it).它工作正常,事实上以/Extranet/login访问资源我必须设置基本身份验证并指定正确的用户名和密码(使用Postman工具执行请求以测试它)。

Ok, this works fine.好的,这很好用。

In my Spring Security configuration is involed this CustomUserDetails class that implements the Spring Security interface UserDetails .在我的 Spring Security 配置中,这个CustomUserDetails类实现了 Spring Security 接口UserDetails

public class CustomUserDetails extends User implements UserDetails {

    private static final long serialVersionUID = 1L;


    public CustomUserDetails(User user){
        super(user);
    }


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        for(UserRole role : this.getUserRoles() ){
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getName());
            authorities.add(grantedAuthority);
        }

        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 true;
    }

    @Override
    public String getUsername() {
        return super.getUsername();
    }

}

An instance of this object contains the user details of the user currently logged.此对象的实例包含当前登录用户的用户详细信息。

Ok my doubt is: how can I retrieve this object from a controller method?好的,我的疑问是:如何从控制器方法中检索此对象? (I think that is should be into the context and that I can retrieve it in some way). (我认为这应该在上下文中,我可以以某种方式检索它)。

I have tryied to do in this way:我尝试这样做:

@RestController
@RequestMapping("/Extranet")
public class AccessController {

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ResponseEntity<String> login(CustomUserDetails userInfo) {

        System.out.println("login() START");

        return ResponseEntity.ok("LOGGED IN");
    }
}

but in this way I obtain an exception like this:但通过这种方式,我获得了这样的异常:

[ERROR] 2017-01-23 14:18:04 [com.betrivius.controller.exceptionHandler.ControllerExceptionHandler.handleException(ControllerExceptionHandler.java:106)] [http-nio-8080-exec-1] ControllerExceptionHandler - Request: http://localhost:8080/Extranet/login  throws: 
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.betrivius.security.bean.CustomUserDetails]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.betrivius.security.bean.CustomUserDetails.<init>()
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:105) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]

It seems that it can't instantialete the CustomUserDetails object.它似乎无法实例化CustomUserDetails对象。 Why?为什么?

From what I know I can retrieve the CustomUserDetails object related to the logged user.据我所知,我可以检索与登录用户相关的CustomUserDetails对象。 How can I do it?我该怎么做?

I also try to do in this way:我也尝试这样做:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<String> login(Principal principal) {

    System.out.println("login() START");

    return ResponseEntity.ok("LOGGED IN");
}

In this way the principal parameter is correctly instantiated and contains an instance of the previous CustomUserDetails object containing the information of the logged user.通过这种方式, principal参数被正确实例化,并包含一个包含登录用户信息的先前CustomUserDetails对象的实例。

So is it the correct way to access to the current logged user information?那么这是访问当前登录用户信息的正确方法吗?

Another doubt is: Why I can pass this Principal principal parameter to my login() method?另一个疑问是:为什么我可以将这个Principal 主体参数传递给我的login()方法? What exactly happen under the hood?引擎盖下到底发生了什么? Who is that effectively pass it to the login() method?谁将它有效地传递给login()方法?

I think that should happen something like this:我认为应该发生这样的事情:

1) There is a POST HttpRequest toward the"/Extranet/login" resource. 1) 有一个针对“/Extranet/login”资源的 POST HttpRequest。 The dispatcher servlet send it to the login() method.调度程序 servlet 将其发送到login()方法。

2) The Principal principal was put into the Spring Context after that the user was enabled for this resource (before that the controller method was called) so the Spring factory can retrieve it from the context and pass it to the login() method. 2) 在为该资源启用用户之后(在调用控制器方法之前)将Principal 主体放入 Spring Context 中,因此 Spring 工厂可以从上下文中检索它并将其传递给login()方法。

But I am absolutly not sure about it.但我绝对不确定。 How exactly works?具体如何运作? What am I missing?我错过了什么?

You probably need then @AuthenticationPrincipal annotation:您可能需要@AuthenticationPrincipal注释:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<String> login(@AuthenticationPrincipal CustomUserDetails userInfo) {

    System.out.println("login() START");

    return ResponseEntity.ok("LOGGED IN");
}

If that still doesn't solve the problem, try debugging using the old method:如果仍然不能解决问题,请尝试使用旧方法进行调试:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<String> login() {

    CustomUserDetails userInfo = (CustomerUserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    ...
}    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Spring Boot中从HttpSessionEvent检索主体信息? - How to retrieve principal information from HttpSessionEvent in Spring Boot? 如何在 websocket controller 中检索当前登录用户 - How to retrieve the current logged in user in a websocket controller 如何从控制器Spring MVC在jsp页面中显示信息 - how to display information in jsp page from controller Spring MVC 从用户到Spring MVC Controller方法的并发请求中的数据完整性 - Data integrity in concurrent requests from a user to a Spring MVC Controller method spring mvc - 如何在不创建视图的情况下从控制器检索值 - spring mvc - How to retrieve values from controller without creating a view 如何将对象从百里香叶形式发送到MVC弹簧启动控制器 - How to send an object from a thymeleaf form to MVC spring boot controller 动态检索 Spring 引导 CORS 从数据库配置 Controller 中的特定方法 - Dynamicallly retrieve Spring Boot CORS Configuration from database for specific method in a Controller Spring MVC从登录的用户获取用户ID - Spring mvc getting user id from logged user Spring 启动 controller 检索用户详情 - Spring boot controller retrieve UserDetails 无法在 Spring Boot 中从 SecurityContextHolder 设置登录用户 - Unable to set logged user from SecurityContextHolder in Spring Boot
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM