【问题标题】:Get authenticated user获取认证用户
【发布时间】:2017-10-25 02:02:12
【问题描述】:

我正在使用 Spring security oauth2 实现一个项目,一切正常,现在我想开始深入挖掘基础知识。我想检查发出请求的用户是否是资源的实际用户所有者,最终结果将是例如:

/private/users/{uuid}/clients 返回指定用户的所有客户端。

所以我的控制器现在看起来像这样:

@RestController
public class HomeController {

    @Autowired
    private UserService userService;

    @GetMapping(value = "/")
    public String index() {
        return "Hello world";
    }

    @GetMapping(value = "/private")
    public String privateTest(Principal principal) {
        User user = userService.get(principal.getName());
        return user.getUuid();
    }

}

编辑:完整的安全代码(工作)以获得更好的解释。

资源服务器配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.headers().frameOptions().disable().and()
                .authorizeRequests()
                .antMatchers("/","/home","/register","/login").permitAll()
                .antMatchers("/private/**").authenticated();
    }
}

CustomUserDetails,getter 和 setter 偏离路线

 public class CustomUserDetails implements UserDetails {

    private Collection<? extends GrantedAuthority> authorities;
    private String password;
    private String username;
    private String uuid;

    public CustomUserDetails(User user) {
        this.username = user.getUsername();
        this.password = user.getPassword();
        this.uuid = user.getUuid();
        this.authorities = translate(user.getRoles());
    }
}

AuthorizationServerConfig

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("my-trusted-client")
                .authorizedGrantTypes("client_credentials", "password")
                .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT").scopes("read","write","trust")
                .resourceIds("oauth2-resource").accessTokenValiditySeconds(5000).secret("secret");
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()");
    }   
}

主要

@SpringBootApplication
public class DummyOauthApplication {

    @Autowired
    private PasswordEncoder passwordEncoder;

    public static void main(String[] args) {
        SpringApplication.run(DummyOauthApplication.class, args);
    }

    @Autowired
    public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository repository, UserService service) throws Exception {
        //Setup a default user if db is empty
        if (repository.count() == 0) {
            service.save(new User("user", "password", UUID.randomUUID().toString(), Arrays.asList(new Role("USER"), new Role("ACTUATOR"))));
        }
        builder.userDetailsService(userDetailsService(repository)).passwordEncoder(passwordEncoder);
    }
    private UserDetailsService userDetailsService(final UserRepository repository) {
        return username -> new CustomUserDetails(repository.findByUsername(username));
    }
}

所以,使用我实施的方式。我可以获取实际用户,但这意味着每次调用端点时都会进行数据库查询。获取用户并匹配用户uuid。

我想找到另一种获取用户的方法,然后比较 uuid = user.getUuid()

提前致谢。

【问题讨论】:

    标签: java spring security spring-boot oauth


    【解决方案1】:

    也许您可以实现自定义 AuthenticationProvider 并将用户详细信息存储为 Principal

    Spring Security Authentication Provider

    【讨论】:

    • 我刚刚尝试过,但在集成方面遇到了问题。我已经更新了我的帖子,以向读者澄清我迄今为止的实施。感谢您的宝贵时间。
    【解决方案2】:

    经过一段时间和很多错误后,我设法找到了一个解决方案,我留在这里。 CustomUserDetails 可以在问题中看到,从那里您可以轻松获取 uuid 并与请求的匹配。

    public static CustomUserDetails getCurrentUser() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();
        if (authentication != null) {
            if (authentication.getPrincipal() instanceof CustomUserDetails) {
                return (CustomUserDetails) authentication.getPrincipal();
            }
        }
        throw new IllegalStateException("User not found!");
    }
    

    编辑:如果你想返回用户,你可以这样做

        public class CustomUserDetails implements UserDetails {
    
        private Collection<? extends GrantedAuthority> authorities;
        private String password;
        private String username;
        private User user;
    
        public CustomUserDetails(User user) {
            this.username = user.getUsername();
            this.password = user.getPassword();
            this.user = user;
            this.authorities = translate(user.getRoles());
        }
    }
    

    然后在 Utils 什么的,

    public static User getCurrentUser() {
            SecurityContext securityContext = SecurityContextHolder.getContext();
            Authentication authentication = securityContext.getAuthentication();
            if (authentication != null) {
                if (authentication.getPrincipal() instanceof CustomUserDetails) {
                     CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
                    return userDetails.getUser();
                }
            }
            throw new IllegalStateException("User not found!");
        }
    

    感谢所有的努力。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多