Я новичок в Spring Boot и действительно изо всех сил пытаюсь это понять. Я не нахожу API-интерфейс безопасности Spring boot очень интуитивным, но я пытаюсь его получить.
Я собираюсь использовать MySql с JPA для получения пользователей из базы данных, но сначала просто для того, чтобы убедиться, что леса безопасности работают, я просто жестко кодирую пользователя из службы сведений о сотрудниках.
После долгих хлопот мне удалось заставить работать базовую аутентификацию, но авторизация не работает. Я отредактировал вопрос, чтобы отразить основную проблему:
Я знаю, что есть другие вопросы, прежде чем люди отметят это как дубликат, я просмотрел все из них, все они дают базовые ответы, которые, как мне кажется, уже работают в моем приложении.
В конце /home путь для домашнего метода, /mama путь для роли мама
Вот код:
//AppSecurityConfig.java
package com.straightwalls.absencemanagement.config;
import com.straightwalls.absencemanagement.service.EmployeeDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
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.configuration.EnableWebSecurity;
import
org.springframework.security.config
.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
protected void configure(HttpSecurity http) throws Exception {
//Disabled for development
http.authorizeRequests()
.antMatchers("/mama").hasRole("MAMA")
.antMatchers("/home").hasAnyRole("ROLE_HEAD", "ROLE_MAMA")
.and()
.formLogin();
}
@Bean
/*
* Returning no op password encoder for now,
* as we are not encoding passwords as no registration
* implemented for Prototype. We would need to add the users from a separate service. W
*
* */
public PasswordEncoder getPasswordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}
//EmployeeDetailsService
package com.straightwalls.absencemanagement.service;
import com.straightwalls.absencemanagement.model.Employee;
import com.straightwalls.absencemanagement.model.Role;
import org.springframework.beans.factory.annotation.Autowired;
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.Component;
import org.springframework.stereotype.Service;
@Service
public class EmployeeDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
if (!username.equals("Mama")){
throw new UsernameNotFoundException(
"You got the wrong Username, should be mama"
);
}
Employee employee = new Employee();
Role role = new Role();
role.setName("HEAD");
employee
.setUsername(username)
.setPassword("1234")
.setRole(role);
return new EmployeePrincipal(employee);
}
}
//EmployeePrincipal.java
package com.straightwalls.absencemanagement.service;
import com.straightwalls.absencemanagement.model.Employee;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Arrays;
import java.util.Collection;
public class EmployeePrincipal implements UserDetails {
private Employee employee;
//Added another default Constructor, incase
public EmployeePrincipal(){
}
public EmployeePrincipal(Employee employee){
this.employee = employee;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_HEAD"));
//return Arrays.asList(new SimpleGrantedAuthority("ROLE_" + employee.getRole().getName()));
}
@Override
public String getPassword() {
return employee.getPassword();
}
@Override
public String getUsername() {
return employee.getUsername();
}
/*
* Methods below are the rubbish methods, we keep as true for now
*
* */
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
//Login.java
package com.straightwalls.absencemanagement.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginApi {
@RequestMapping("/")
public String index(){
return "Straight Walls absence management!";
}
@RequestMapping("/home")
public String home(){
return "Welcome to Home!";
}
/**
* This method can be deleted in the end
*
*/
@RequestMapping("/mama")
public String roleTest(){
return "This end point is only for Mama!";
}
}
//Employee.java
package com.straightwalls.absencemanagement.model;
import org.hibernate.annotations.Fetch;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Entity
public class Employee {
@Id
private long id;
private String firstName;
private String lastName;
private String username;
private String password;
private String startDate;
@ManyToOne
@JoinColumn(name = "roleId", referencedColumnName = "id")
private Role role;
@ManyToOne
@JoinColumn(name = "departmentId", referencedColumnName = "id")
private Department department;
public Employee(){
}
public long getId() {
return id;
}
public Employee setId(long id) {
this.id = id;
return this;
}
public String getFirstName() {
return firstName;
}
public Employee setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public String getLastName() {
return lastName;
}
public Employee setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public String getUsername() {
return username;
}
public Employee setUsername(String username) {
this.username = username;
return this;
}
public String getPassword() {
return password;
}
public Employee setPassword(String password) {
this.password = password;
return this;
}
public String getStartDate() {
return startDate;
}
public Employee setStartDate(LocalDate startDate) {
this.startDate =
startDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
return this;
}
public Role getRole() {
return role;
}
public Employee setRole(Role role) {
this.role = role;
return this;
}
public Department getDepartment() {
return department;
}
public Employee setDepartment(Department department) {
this.department = department;
return this;
}
}
Я вхожу в систему с фиктивной ролью HEAD. Таким образом, я должен иметь доступ: /, /home, но не /mama. Я не могу получить доступ к /home, даже если роль была правильно определена.
В моем базовом пакете у меня есть следующие пакеты: config: с этим файлом конфигурации, модель: API всех сущностей: репозиторий контроллеров: репозитории (еще не используются) служба: где у меня есть класс EmployeeDetailsService и EmployeeDetails
Буду очень признателен за любой совет, так как я ожидаю, что это сработает, но он просто не выдает никаких ошибок и просто постоянно говорит о неверных учетных данных, хотя я ввел имя пользователя Mama и пароль Mama и попытался использовать NoOpPasswordEncoder.
Удалось исправить это, очистив код и внеся несколько изменений в метод grantAuthorities, который не нуждался в ROLE_