自定义 UserDetailsService Impl 未在 SpringSecurity 中调用
Custom UserDetailsService Impl not being Called in SpringSecurity
我的自定义 UserDetailsService
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import br.com.fimd.entidades.Usuario;
import br.com.fimd.service.UsuarioService;
@Transactional(readOnly=true)
@Service("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private UsuarioService usuarioService;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Usuario usuario = usuarioService.findUserByEmail(email);
if(usuario == null) {
throw new UsernameNotFoundException("Usuário nao encontrado.");
}
return new User(usuario.getEmail(), usuario.getSenha(), usuario.getAuthorities());
}
}
我的安全配置
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsServiceImpl")
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().disable().
csrf().disable().authorizeRequests()
.antMatchers("/home").permitAll()
.antMatchers("/public/**").permitAll()
.antMatchers("/private/**").hasRole("USER")
//.antMatchers("/admin*").access("hasRole('ROLE_ADMIN')")
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
//.addFilterBefore(new JWTAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class)
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**");
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
我的用户实体
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@Entity
@Table(name = "usuarios")
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = { "createdAt", "updatedAt" }, allowGetters = true)
public class Usuario implements UserDetails, Serializable{
private static final long serialVersionUID = 4038437690572999966L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;
@NotBlank
private String nome;
@NotBlank
private String email;
@NotBlank
private String senha;
@NotBlank
private String cpf;
@Column
private boolean ativo;
@ManyToMany
@JoinTable(name="perfil_usuario", joinColumns=
{@JoinColumn(name="user_id")}, inverseJoinColumns=
{@JoinColumn(name="tipo_perfil")})
private Set<Perfil> perfis = new HashSet<>();
@OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Investimento> investimentos;
@OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Extrato> extratos;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
public boolean isAtivo() {
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public Set<Perfil> getPerfis() {
return perfis;
}
public void setPerfis(Set<Perfil> perfis) {
this.perfis = perfis;
}
public List<Investimento> getInvestimentos() {
return investimentos;
}
public void setInvestimentos(List<Investimento> investimentos) {
this.investimentos = investimentos;
}
public List<Extrato> getExtratos() {
return extratos;
}
public void setExtratos(List<Extrato> extratos) {
this.extratos = extratos;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.perfis;
}
@Override
public String getPassword() {
return this.senha;
}
@Override
public String getUsername() {
return this.email;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
我的 Perfil 实体
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.springframework.security.core.GrantedAuthority;
@Entity
public class Perfil implements GrantedAuthority{
private static final long serialVersionUID = 1L;
@Id
private String tipoPerfil;
@ManyToMany(mappedBy="perfis")
private List<Usuario> usuarios;
public List<Usuario> getUsuarios() {
return usuarios;
}
public void setUsuarios(List<Usuario> usuarios) {
this.usuarios = usuarios;
}
public String getTipoPerfil() {
return tipoPerfil;
}
public void setTipoPerfil(String tipoPerfil) {
this.tipoPerfil = tipoPerfil;
}
@Override
public String getAuthority() {
return this.tipoPerfil;
}
}
我的 Spring 过滤器初始化器
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
@Configuration
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
当我调用“/private/service”时,我的 loadUserByUsername 从未被调用,我的应用程序曾向我发送 403 禁止访问,访问被拒绝。
为什么?
我尝试了很多来自互联网的教程,我的代码似乎是正确的,我正在使用 spring starter 2.0.5.RELEASE
我已经尝试从 SecurityConfiguration 中的 @Bean 方法调用 userDetailsService
您的安全配置不完整,您还需要提供登录信息:
.formLogin()
.loginPage("/login.html")
.defaultSuccessUrl("/home")
.failureUrl("/login.html?error=true")
否则您的所有请求都将未经授权。请看这个教程:
只有当应用程序收到 POST 以使用用户名和密码登录 url 时,您的自定义 UserDetails 服务才会被调用,否则它将没有要授权的数据。
我的自定义 UserDetailsService
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import br.com.fimd.entidades.Usuario;
import br.com.fimd.service.UsuarioService;
@Transactional(readOnly=true)
@Service("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private UsuarioService usuarioService;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Usuario usuario = usuarioService.findUserByEmail(email);
if(usuario == null) {
throw new UsernameNotFoundException("Usuário nao encontrado.");
}
return new User(usuario.getEmail(), usuario.getSenha(), usuario.getAuthorities());
}
}
我的安全配置
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsServiceImpl")
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().disable().
csrf().disable().authorizeRequests()
.antMatchers("/home").permitAll()
.antMatchers("/public/**").permitAll()
.antMatchers("/private/**").hasRole("USER")
//.antMatchers("/admin*").access("hasRole('ROLE_ADMIN')")
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
//.addFilterBefore(new JWTAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class)
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**");
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
我的用户实体
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@Entity
@Table(name = "usuarios")
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = { "createdAt", "updatedAt" }, allowGetters = true)
public class Usuario implements UserDetails, Serializable{
private static final long serialVersionUID = 4038437690572999966L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;
@NotBlank
private String nome;
@NotBlank
private String email;
@NotBlank
private String senha;
@NotBlank
private String cpf;
@Column
private boolean ativo;
@ManyToMany
@JoinTable(name="perfil_usuario", joinColumns=
{@JoinColumn(name="user_id")}, inverseJoinColumns=
{@JoinColumn(name="tipo_perfil")})
private Set<Perfil> perfis = new HashSet<>();
@OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Investimento> investimentos;
@OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Extrato> extratos;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
public boolean isAtivo() {
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public Set<Perfil> getPerfis() {
return perfis;
}
public void setPerfis(Set<Perfil> perfis) {
this.perfis = perfis;
}
public List<Investimento> getInvestimentos() {
return investimentos;
}
public void setInvestimentos(List<Investimento> investimentos) {
this.investimentos = investimentos;
}
public List<Extrato> getExtratos() {
return extratos;
}
public void setExtratos(List<Extrato> extratos) {
this.extratos = extratos;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.perfis;
}
@Override
public String getPassword() {
return this.senha;
}
@Override
public String getUsername() {
return this.email;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
我的 Perfil 实体
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.springframework.security.core.GrantedAuthority;
@Entity
public class Perfil implements GrantedAuthority{
private static final long serialVersionUID = 1L;
@Id
private String tipoPerfil;
@ManyToMany(mappedBy="perfis")
private List<Usuario> usuarios;
public List<Usuario> getUsuarios() {
return usuarios;
}
public void setUsuarios(List<Usuario> usuarios) {
this.usuarios = usuarios;
}
public String getTipoPerfil() {
return tipoPerfil;
}
public void setTipoPerfil(String tipoPerfil) {
this.tipoPerfil = tipoPerfil;
}
@Override
public String getAuthority() {
return this.tipoPerfil;
}
}
我的 Spring 过滤器初始化器
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
@Configuration
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
当我调用“/private/service”时,我的 loadUserByUsername 从未被调用,我的应用程序曾向我发送 403 禁止访问,访问被拒绝。 为什么? 我尝试了很多来自互联网的教程,我的代码似乎是正确的,我正在使用 spring starter 2.0.5.RELEASE
我已经尝试从 SecurityConfiguration 中的 @Bean 方法调用 userDetailsService
您的安全配置不完整,您还需要提供登录信息:
.formLogin()
.loginPage("/login.html")
.defaultSuccessUrl("/home")
.failureUrl("/login.html?error=true")
否则您的所有请求都将未经授权。请看这个教程:
只有当应用程序收到 POST 以使用用户名和密码登录 url 时,您的自定义 UserDetails 服务才会被调用,否则它将没有要授权的数据。