Java Spring启动表单登录自定义用户详细信息服务授权不工作
我是Spring Boot的初学者,很难做到这一点。我觉得SpringBoot的安全API一点也不直观,但我正在努力实现它 我将使用MySql和JPA从数据库中获取用户, 但最初只是为了确保安全脚手架工作,我只是从员工详细信息服务硬编码一个用户 在经历了很多麻烦之后,我成功地获得了基本的身份验证,但是授权不起作用。 我对问题进行了编辑,以反映基本问题: 我知道在人们将此标记为重复之前还有其他问题,我已经检查了所有这些问题,他们都给出了我认为已经在我的应用程序中运行的基本答案 最后 /主路径用于主方法, /妈妈路径是为角色妈妈 代码如下:Java Spring启动表单登录自定义用户详细信息服务授权不工作,java,spring-boot,spring-security,spring-security-rest,Java,Spring Boot,Spring Security,Spring Security Rest,我是Spring Boot的初学者,很难做到这一点。我觉得SpringBoot的安全API一点也不直观,但我正在努力实现它 我将使用MySql和JPA从数据库中获取用户, 但最初只是为了确保安全脚手架工作,我只是从员工详细信息服务硬编码一个用户 在经历了很多麻烦之后,我成功地获得了基本的身份验证,但是授权不起作用。 我对问题进行了编辑,以反映基本问题: 我知道在人们将此标记为重复之前还有其他问题,我已经检查了所有这些问题,他们都给出了我认为已经在我的应用程序中运行的基本答案 最后 /主路径用于主
//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;
}
}
//AppSecurityConfig.java
包com.streamwalls.absencemanagement.config;
导入com.streamwalls.absencemanagement.service.employeedetails服务;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
进口
org.springframework.security.config
.annotation.authentication.builders.AuthenticationManagerBuilder;
导入org.springframework.security.config.annotation.web.builders.HttpSecurity;
导入org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
进口
org.springframework.security.config
.annotation.web.configuration.WebSecurity配置适配器;
导入org.springframework.security.core.userdetails.userdetails服务;
导入org.springframework.security.crypto.password.NoOpPasswordEncoder;
导入org.springframework.security.crypto.password.PasswordEncoder;
@配置
@启用Web安全性
公共类AppSecurityConfig扩展了WebSecurity配置适配器{
@自动连线
私有用户详细信息服务用户详细信息服务;
@凌驾
受保护的无效配置(AuthenticationManagerBuilder auth)引发异常{
auth.userDetailsService(userDetailsService);
}
受保护的无效配置(HttpSecurity http)引发异常{
//残疾人促进发展
http.authorizeRequests()
.antMatchers(“/mama”).hasRole(“mama”)
.antMatchers(“/home”).hasAnyRole(“角色头”、“角色妈妈”)
.及()
.formLogin();
}
@豆子
/*
*目前没有返回操作密码编码器,
*因为我们没有将密码编码为“无注册”
*为原型实现。我们需要从单独的服务添加用户。W
*
* */
公共密码编码器getPasswordEncoder(){
返回NoOpPasswordEncoder.getInstance();
}
}
//雇员就业服务
包com.slightwalls.absencemanagement.service;
导入com.streamwalls.absencemanagement.model.Employee;
导入com.slightwalls.absencemanagement.model.Role;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.security.core.userdetails.userdetails;
导入org.springframework.security.core.userdetails.userdetails服务;
导入org.springframework.security.core.userdetails.UsernameNotFoundException;
导入org.springframework.stereotype.Component;
导入org.springframework.stereotype.Service;
@服务
公共类EmployeeDetailsService实现UserDetailsService{
@凌驾
公共用户详细信息loadUserByUsername(字符串用户名)
抛出UsernameNotFoundException{
如果(!username.equals(“Mama”)){
抛出新UsernameNotFoundException(
“你的用户名错了,应该是妈妈”
);
}
员工=新员工();
角色=新角色();
角色。设置名称(“头”);
雇员
.setUsername(用户名)
.setPassword(“1234”)
.setRole(role);
返回新员工主(员工);
}
}
//EmployeePrincipal.java
包com.slightwalls.absencemanagement.service;
导入com.streamwalls.absencemanagement.model.Employee;
导入org.springframework.security.core.GrantedAuthority;
导入org.springframework.security.core.authority.SimpleGrantedAuthority;
导入org.springframework.security.core.userdetails.userdetails;
导入java.util.array;
导入java.util.Collection;
公共类EmployeePrincipal实现UserDetails{
私人雇员;
//添加了另一个默认构造函数,以防万一
公共雇员原则(){
}
公共雇员负责人(雇员){
this.employee=employee;
}
@凌驾
public Collection通过清理代码并对grantedAuthories方法进行一些更改来解决这个问题,GrantedAuthories方法不需要这个角色_
还通过取消角色更改了hasRole、hasAnyRole和hasAnyAuthority_
不知道为什么,但它现在起作用了
此外,API现在更容易理解
以下是更新的代码:
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
/*auth.inMemoryAuthentication()
.withUser("appuser").password("1234").roles("HEAD")
.and()
.withUser("Mama").password("Mama").roles("MAMA");*/
}
@Override
/*
* Now we have learnt the basics of Spring Security & Authrization method is completed.
* Lets fix Authentication first!
* Got it to work with hasAuthority & hasAnyAuthority but not with roles, not sure why, but it works atm
*
* */
protected void configure(HttpSecurity http) throws Exception {
//Disabled for development
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/mama").hasAuthority("MAMA")
.antMatchers("/home").hasAnyAuthority("HEAD", "MAMA")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.defaultSuccessUrl("/home");
}
@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.java
@Service
public class EmployeeDetailsService implements UserDetailsService {
@Override
/*
* First, we are testing the Employee details service, independent of the Database, just to make sure we have this part working,
* For the purpose of these prototypes, we wont use password encoder because we are not registering,
*
* */
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
public class EmployeePrincipal implements UserDetails {
private Employee employee;
public EmployeePrincipal(Employee employee){
this.employee = employee;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(employee.getRole().getName()));
return authorities;
}
@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;
}
}
@RestController
public class LoginApi {
@RequestMapping("/")
public String index(){
return "Index"
}
@RequestMapping("/home")
public String home(){
return "Home!";
}
/*
* This method can be deleted in the end
* */
@RequestMapping("/mama")
public String roleTest(){
return "This end point is only for Mama!";
}
}
@配置
@启用Web安全性
公共类AppSecurityConfig扩展了WebSecurity配置适配器{
@自动连线
用户详细信息服务用户详细信息服务;
@凌驾
受保护的无效配置(AuthenticationManagerBuilder auth)引发异常{
auth.userDetailsService(userDetailsService);
/*auth.inMemoryAuthentication()
.withUser(“appuser”)。密码(“1234”)。角色(“头”)
.及()
.withUser(“Mama”)。密码(“Mama”)。角色(“Mama”)*/
}
@凌驾
/*
*现在,我们已经学习了Spring安全性的基础知识&身份验证方法已经完成。
*让我们先修复身份验证!
*让它与hasAuthority一起工作&hasAnyAuthority但不与角色一起工作,不确定为什么,但它可以工作
*
* */
受保护的无效配置(HttpSecurity http)引发异常