Oauth 2:Spring Boot 2:身份验证服务器/oauth/check_token 将 user_name 返回为 null [英] Oauth 2: Spring Boot 2: Auth Server /oauth/check_token returns user_name as null

查看:71
本文介绍了Oauth 2:Spring Boot 2:身份验证服务器/oauth/check_token 将 user_name 返回为 null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了 2 个不同的服务器:auth 服务器和一个使用 Spring Boot 2.1.6.RELEASE 和 spring-cloud-starter-oauth2 版本 Greenwich.RELEASE 的资源服务器

I have implemented 2 distinct servers: auth server and a resource server using Spring Boot 2.1.6.RELEASE and spring-cloud-starter-oauth2 version Greenwich.RELEASE

我能够从身份验证服务器成功获取 access_token,使用它访问资源服务器上受保护的 api.

I am able to successfully get an access_token from auth server, use it to access protected api on resource server.

但是,我无法在身份验证服务器的/oauth/check_token 端点返回的响应中获取 user_name,我可以确认 user_name 存在于用户表中.

However I am not able to get user_name in the response returned by auth server's /oauth/check_token endpoint I can confirm that user_name is present in user table.

curl http://localhost:5000/oauth/check_token?token=a3ee84ee-6d3a-4a8f-af19-5446b55c637f | jq . 

返回以下内容:

  {
    "aud": [
      "article"
    ],
    "user_name": null,
    "scope": [
      "READ",
      "WRITE",
      "UPDATE",
      "DELETE"
    ],
    "active": true,
    "exp": 1563849438,
    "authorities": [
      "ROLE_administrator",
      "create_article",
      "read_article",
      "delete_article",
      "update_article"
    ],
    "client_id": "myclient"
  }

授权服务器配置

@Configuration
public class AuthorizationServerConfiguration implements AuthorizationServerConfigurer {

    private PasswordEncoder passwordEncoder;
    private DataSource dataSource;
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Autowired
    public AuthorizationServerConfiguration(
            PasswordEncoder passwordEncoder,
            DataSource dataSource,
            AuthenticationManager authenticationManager) {
        this.passwordEncoder = passwordEncoder;
        this.dataSource = dataSource;
        this.authenticationManager = authenticationManager;
    }

    @Bean
    TokenStore jdbcTokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        return new JwtAccessTokenConverter();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
      //  security.checkTokenAccess("isAuthenticated()").tokenKeyAccess("permitAll()");
        security.checkTokenAccess("permitAll()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.tokenStore(jdbcTokenStore());
        endpoints.authenticationManager(authenticationManager);
        //TODO JWT
        // endpoints.accessTokenConverter(accessTokenConverter());
    }
}

网络安全配置

@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers("/version").permitAll()
                .antMatchers("/api/**").authenticated();
    }
}

UserDetailsS​​erviceImpl

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
    private UserRepository userRepository;

    @Autowired
    public UserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        Optional<User> optionalUser = userRepository.findByUserName(userName);
        optionalUser.orElseThrow(() -> new UsernameNotFoundException("Username or password wrong"));

        UserDetails userDetails = new AuthUserDetail(optionalUser.get());
        new AccountStatusUserDetailsChecker().check(userDetails);
        return userDetails;
    }
}

主要应用类

@SpringBootApplication
@EnableAuthorizationServer
public class MyApplication {

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

}

AuthUserDetail

package com.myapplication.models;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class AuthUserDetail extends User implements UserDetails {

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

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();

        getRoles().forEach(role -> {
            grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
            role.getPermissions().forEach(permission -> {
                grantedAuthorities.add(new SimpleGrantedAuthority(permission.getName()));
            });

        });
        return grantedAuthorities;
    }

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

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

    @Override
    public boolean isAccountNonExpired() {
        return super.isAccountNonExpired();
    }

    @Override
    public boolean isAccountNonLocked() {
        return super.isAccountNonLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return super.isCredentialsNonExpired();
    }

    @Override
    public boolean isEnabled() {
        return super.isEnabled();
    }
}

用户

package com.myapplication.models;

import lombok.Data;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "user")
@Data
public class User {
    public User() {
    }

    public User(User user) {
        this.userName = user.getUserName();
        this.password = user.getPassword();
        this.email = user.getEmail();
        this.enabled = user.isEnabled();
        this.accountNonExpired = user.isAccountNonExpired();
        this.credentialsNonExpired = user.isCredentialsNonExpired();
        this.accountNonLocked = user.isAccountNonLocked();
        this.roles = user.getRoles();
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "user_name")
    private String userName;
    @Column(name = "password")
    private String password;
    @Column(name = "email")
    private String email;
    @Column(name = "enabled")
    private boolean enabled;
    @Column(name = "account_non_expired")
    private boolean accountNonExpired;
    @Column(name = "credentials_non_expired")
    private boolean credentialsNonExpired;
    @Column(name = "account_non_locked")
    private boolean accountNonLocked;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "role_user", joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            inverseJoinColumns = {
                    @JoinColumn(name = "role_id", referencedColumnName = "id")})
    private List<Role> roles;
}

用户表 ddl

create table if not exists user
(
    id int auto_increment
        primary key,
    user_name varchar(100) not null,
    password varchar(1024) not null,
    email varchar(1024) not null,
    enabled tinyint not null,
    account_non_expired tinyint not null,
    credentials_non_expired tinyint not null,
    account_non_locked tinyint not null,
    constraint user_name
        unique (user_name)
);

推荐答案

在将我的用户表的列名从驼峰命名修改为 underscore_case 后,我遇到了同样的问题.

I got the same problem after I modified column names of my user table from camelCase to underscore_case.

为了解决这个问题,我确保用户、权限和角色类正在实现 Serializable 类

To resolve this I made sure the user, permission and role class is implementing Serializable class

@Entity
@Table(name = "user")
public class User implements Serializable {
----
----
}

如果添加,也删除以下 spring jpa 属性

and also remove the following spring jpa property if added

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

这篇关于Oauth 2:Spring Boot 2:身份验证服务器/oauth/check_token 将 user_name 返回为 null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆