问题描述
我已经实现了 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();
}
}
UserDetailsServiceImpl
@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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!