我正在使用包含用户详细信息的Postgres db在Spring Boot上创建OAuth服务器。
当我提供正确的用户名和密码[200 OK]时,身份验证请求工作正常,我可以按预期取回身份验证承载令牌,但是如果凭据错误,代码将进入连续循环而不返回任何响应。它会不断调用UserDetails Service的loadUserByUsername方法,并且即使抛出错误也不会中断。
下面是涉及的不同组件的代码片段。如果有人可以通过查看下面的代码来分享自己的知识,那么我在哪里做错了,那将非常有帮助。
授权服务器配置
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.resourceIds("myResource")
.secret("{noop}secret")
.accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes.
refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes.
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
资源服务器配置
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {
@Autowired
private PasswordEncoder userPasswordEncoder;
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManagerBean())
.userDetailsService(customUserDetailsService)
.passwordEncoder(userPasswordEncoder);
}
}
角色实体
@Entity
@Table(name="roles")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="role_id")
private int roleId;
@Column(name="role")
private String role;
public Role() {}
public int getRoleId() {
return roleId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
用户实体
@Entity
@Table(name="users")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="user_id")
private int id;
@Column
private String email;
@Column
private String name;
@Column
private String password;
@Column
private String lastName;
@Column
private String active;
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
// @JoinTable(name="user_role",
// joinColumns = @JoinColumn(name="user_id"),
// inverseJoinColumns= @JoinColumn(name="role_id")
//
// )
@JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
public User() { }
public User(User users) {
this.active = users.active;
this.email = users.email;
this.id = users.id;
this.lastName = users.lastName;
this.name = users.name;
this.password = users.password;
this.roles = users.roles;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
自定义用户详细信息实体
public class CustomUserDetails implements UserDetails {
private String username;
private String password;
private Collection authorities;
public CustomUserDetails(User user) {
this.username = user.getName();
this.password = user.getPassword();
this.authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority("ROLE_"+role.getRole()))
.collect(Collectors.toList());
}
@Override
public Collection getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
用户存储库
public interface UserRepository extends JpaRepository<User, Integer>{
public Optional<User> findByName(String username);
}
自定义用户详细信息服务Impl
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println(username); ***// this keeps printing endless times in case of bad credentials***
Optional<User> user = userRepository.findByName(username);
return new CustomUserDetails(
user.orElseThrow(
() -> new UsernameNotFoundException("User not found")
)
);
}
}
询问是否有人可以干预,让我知道我要去哪里了。我认为这也可能是一个非常小的/愚蠢的错误。寻求您的帮助。预先感谢。
PS:这是我遵循的教程的链接-> https://thecuriousdev.org/spring-security-oauth2