我有一个类似于在线食品春季订购系统平台的项目 我正在将 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();
}
}
但是我工作......嗯
请帮我修复或给我另一种方法。非常感谢....
让我们看看如何解决这个问题
@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();
}
}