Spring Security 6 使用数据库中的用户进行身份验证和授权

问题描述 投票:0回答:1

我有一个类似于在线食品春季订购系统平台的项目 我正在将 Hibernate 与两个模型一起使用,如下所示:

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String username;
    private String password;
    private String email;
    private Long balance;
}

@Entity
@Table(name = "user_roles")
public class UserRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
}

我认为这个系统有三个角色:ROLE_SYSADMIN、ROLE_ADMIN(对于食品店)、ROLE_CUSTOMER 用户和用户角色存储在数据库中。

如何使用 Spring Boot 6 为我的应用程序配置授权和身份验证?

我搜索并制作了一些代码。 首先,我编写了一个像这样的自定义 UserDetailService

@Service
public class HiruezUserDetailsService implements UserDetailsService {

    private final UserRepository userRepository;
    
    public HiruezUserDetailsService(UserRepository userRepository) {
        super();
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
        return new HiruezUserDetails(user);
    }

}

然后,自定义用户详细信息,例如:

public class HiruezUserDetails implements UserDetails {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private final User user;

    public HiruezUserDetails(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.singleton(new SimpleGrantedAuthority("ROLE_" + user.getRole().getName()));
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        
        return false;
    }

    @Override
    public boolean isEnabled() {
        
        return false;
    }

}

最后是SecurityConfig.java,如:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    private HiruezUserDetailsService hiruezUserDetailsService;
    
    @Bean
    public PasswordEncoder passwordEncoder( ) {
        return new BCryptPasswordEncoder();
    }
    
    @Bean
    public JdbcUserDetailsManager jdbcUserDetailManager() {
        JdbcUserDetailsManager userDetailManager = new JdbcUserDetailsManager();
        userDetailManager.setJdbcTemplate(jdbcTemplate);
        return userDetailManager;
    }
    
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(hiruezUserDetailsService)
            .passwordEncoder(passwordEncoder());
    }
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authorize) -> authorize
                .requestMatchers("/admin/**").hasRole("SYSADMIN")
                .requestMatchers("/store/**").hasRole("ADMIN")
                .requestMatchers("/customer/**").hasRole("CUSTOMER")
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults())
            .formLogin(form -> form
                    .loginPage("/login")
                    .permitAll()
                )
            .logout((logout) -> logout.logoutUrl("/logout"));

        return http.build();
    }
}

但是我工作......嗯

请帮我修复或给我另一种方法。非常感谢....

spring spring-mvc spring-security
1个回答
0
投票

让我们看看如何解决这个问题

  • 使用管理员之前设置的新列 roleId 更新您的用户表实体

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users")
public class User implements UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String password;
    private String email;
    private Long balance;

    private Long roleId; // new field , this field will set when admin create user by selecting role

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
        //authorities.add(new SimpleGrantedAuthority("ROLE_SYSADMIN"));
        //authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        //authorities.add(new SimpleGrantedAuthority("ROLE_CUSTOMER"));

        // we will set the permission leater

        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, Long> {
}

  • 用户角色表和存储库
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "user_roles")
public class UserRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

public interface UserRoleRepository extends JpaRepository<UserRole, Long> {
}

  • 创建自定义身份验证提供程序以从用户角色表中读取权限名称并用于身份验证和授权
@Component
@RequiredArgsConstructor
public class UserAuthenticationProvider implements AuthenticationProvider, UserDetailsService {

    private final UserRepository userRepository;
    private final UserRoleRepository userRoleRepository;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        final String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
        if (Utils.isEmpty(username)) {
            throw new BadCredentialsException("invalid login details");
        }
        // get user details using Spring security user details service
        UserDetails user = null;
        try {
            user = loadUserByUsername(username);

        } catch (UsernameNotFoundException exception) {
            throw new BadCredentialsException("invalid login details");
        }
        return createSuccessfulAuthentication(authentication, user);
    }

    private Authentication createSuccessfulAuthentication(final Authentication authentication, final UserDetails user) {

        User dbUser =  userRepository.findByUsername(user.getUsername());
        UserRole userRole = userRoleRepository.findById(dbUser.getRoleId());

        List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(userRole.getName()));


        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(), authentication.getCredentials(), authorities);
        token.setDetails(authentication.getDetails());
        return token;
    }

    @Override
    public boolean supports(Class < ? > authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        return userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found"));
    }
}

  • 根据您的需要更新您的安全性,但使用上述身份验证提供商

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final UserAuthenticationProvider userAuthenticationProvider;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // ...
                .authenticationProvider(userAuthenticationProvider);
        return http.build();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.