我正在尝试创建一个身份验证和授权系统,但是出了点问题,但是我无法弄清楚。这些是类:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("datasource")
DataSource dataSource;
@Autowired
CustomUserDetailsService customUserDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
/*authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());*/
authenticationManagerBuilder.userDetailsService(customUserDetailsService);
authenticationManagerBuilder
.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username,pass, enabled from users where username=?")
.authoritiesByUsernameQuery(
"SELECT u.username, r.name FROM users u" +
"INNER JOIN user_roles ur on u.userid = ur.user_id + "
+ "INNER JOIN roles r on ur.role_id=r.id where username=?");
}
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/api/auth/**")
.permitAll()
.antMatchers("/api/user/checkUsernameAvailability", "/api/user/checkEmailAvailability")
.permitAll()
.antMatchers(HttpMethod.GET, "/api/polls/**", "/api/users/**")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
型号:
@Entity
@Table(name="users")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="userid")
private Long id;
@NotNull
@Size(min=2, message="Lastname should have atleast 2 characters")
@Column(name="lastname")
private String lastname;
@NotNull
@Size(min=2, message="Name should have atleast 2 characters")
@Column(name="name")
private String firstname;
@NotNull
@Column(name="email")
private String email;
@NotNull
@Size(min=4, message="Username should have atleast 4 characters")
@Column(name="username")
private String username;
@NotNull
@Column(name="birthdate")
private Date birthdate;
@NotNull
@Size(min=8, message="Password should have atleast 8 characters")
@Column(name="pass")
private String password;
@Column(name="city")
private String city;
@Column(name="state")
private String state;
@Column(name = "enabled")
private Short enabled;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "user_roles", joinColumns = {
@JoinColumn(name = "user_id") }, inverseJoinColumns = {
@JoinColumn(name = "role_id") })
private Set<Role> roles;
public User() {
}
public User(String username, String password) {
super();
this.username = username;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Date getBirthdate() {
return birthdate;
}
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
public Set<Role> getRoles() {
Set<Role> roles = new HashSet<>();
roles.add(new Role());
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public Short getEnabled() {
return enabled;
}
public void setEnabled(Short enabled) {
this.enabled = enabled;
}
}
//
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column()
private Long id;
@Enumerated(EnumType.STRING)
@NaturalId
@Column(length = 60)
private RoleName name;
public Role() {
}
public Role(RoleName name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public RoleName getName() {
return name;
}
public void setName(RoleName name) {
this.name = name;
}
}
public enum RoleName {
ROLE_USER,
ROLE_ADMIN
}
我已经创建了JWTTokenProvider,UserServiceDetailsService,UserServiceDetails和JWTAuthenticationEntryPoint。我还在.properties文件中配置了数据库。注册进行得很好,但是创建的用户的登录返回401(未授权)。
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
UserRepository userRepository;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
JwtTokenProvider tokenProvider;
@PostMapping("/login")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsernameOrEmail(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));
}
@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
if(userRepository.existsByUsername(signUpRequest.getUsername())) {
return new ResponseEntity(new ApiResponse(false, "Username is already taken!"),
HttpStatus.BAD_REQUEST);
}
if(userRepository.existsByEmail(signUpRequest.getEmail())) {
return new ResponseEntity(new ApiResponse(false, "Email Address already in use!"),
HttpStatus.BAD_REQUEST);
}
// Creating user's account
// User user = new User(signUpRequest.getName(), signUpRequest.getUsername(),
// signUpRequest.getEmail(), signUpRequest.getPassword());
User user = new User();
user.setFirstname(signUpRequest.getName());
user.setLastname("Bla bla");
user.setUsername(signUpRequest.getUsername());
user.setEmail(signUpRequest.getEmail());
user.setPassword(signUpRequest.getPassword());
user.setBirthdate(Calendar.getInstance().getTime());
user.setPassword(passwordEncoder.encode(user.getPassword()));
// Use this code once the roles are in database
// Role userRole = roleRepository.findByName(RoleName.ROLE_USER)
// .orElseThrow(() -> new AppException("User Role not set."));
if(userRepository.numberOfUsers() == 0) {
Role userRole = new Role(RoleName.ROLE_ADMIN);
user.setRoles(Collections.singleton(userRole));
} else {
Role userRole = new Role(RoleName.ROLE_USER);
user.setRoles(Collections.singleton(userRole));
}
user.setEnabled((short)1);
User result = userRepository.save(user);
URI location = ServletUriComponentsBuilder
.fromCurrentContextPath().path("/api/users/{username}")
.buildAndExpand(result.getUsername()).toUri();
return ResponseEntity.created(location).body(new ApiResponse(true, "User registered successfully"));
}
}
有人可以帮我吗?
编辑
spring.jpa.database = POSTGRESQL
spring.datasource.platform = postgres
spring.jpa.show-sql = true
spring.datasource.driver-class-name = org.postgresql.Driver
# disable driver's feature detection
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
# without detection you have to set the dialect by hand
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
# parametri za konekciju (zameniti X sa odgovarajucim parametrima)
spring.jpa.hibernate.ddl-auto = create
spring.datasource.jdbcUrl = jdbc:postgresql://localhost:5432/resttest
spring.datasource.username = postgres
spring.datasource.password = klasikaK1
#
## proxy problem sa bean-ovima
spring.jackson.serialization.fail-on-empty-beans = false
#port
server.port=8085
## App Properties
app.jwtSecret= JWTSuperSecretKey
app.jwtExpirationInMs = 604800000
没有消息,只有代码401(未授权)。我能够创建一个用户,并且密码在数据库中被散列。