Spring Security Practice

Okay, here is a simple example to demonstrate how to use Spring Security to implement role-based data permission control.

First, in Spring Security, you can use the @PreAuthorize annotation to configure data permission control. The @PreAuthorize annotation can be used to verify the permissions of parameters before calling the method. If the permission verification fails, an exception will be thrown.

  1. Create entity classes and data access layer

First, we create a User entity class and a UserRepository data access layer. The User entity class contains a username field and a departmentId field, which are used to represent the user's account name and department. The UserRepository data access layer provides a findByDepartmentId method to obtain all user information under the department based on the department ID.

@Entity

public class User {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

private String username;

private Long departmentId;

// getters and setters

}

@Repository

public interface UserRepository extends JpaRepository<User, Long> {

List<User> findByDepartmentId(Long departmentId);

}

  1. Create service layer

Next, we create a UserService service layer to provide query services for user information. In the UserService service layer, we define a getUsersByDepartmentId method, which is used to obtain all user information under the department based on the department ID. In the method, we first obtain the role and department information of the currently logged in user, and then filter the returned user list based on the role and department information of the currently logged in user, and only return user information that meets the conditions.

@Service

public class UserService {

@Autowired

private UserRepository userRepository;

@Autowired

private DepartmentService departmentService;

public List<User> getUsersByDepartmentId(Long departmentId) {

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

String currentUsername = authentication.getName();

Set<String> currentRoles = authentication.getAuthorities().stream()

.map(GrantedAuthority::getAuthority)

.collect(Collectors.toSet());

Long currentDepartmentId = departmentService.getDepartmentIdByUsername(currentUsername);

List<User> users = userRepository.findByDepartmentId(departmentId);

if (!currentRoles.contains("ADMIN") && !Objects.equals(currentDepartmentId, departmentId)) {

users = users.stream()

.filter(user -> Objects.equals(user.getDepartmentId(), currentDepartmentId))

.collect(Collectors.toList());

}

return users;

}

}

  1. Create controller

Finally, we create a UserController controller to provide an interface for user information query. In the UserController controller, we use the @PreAuthorize annotation to configure permission control on the interface. Only users with the ADMIN role or the corresponding user with read permission can access this interface.

@RestController

public class UserController {

@Autowired

private UserService userService;

@GetMapping("/users/{departmentId}")

@PreAuthorize("hasRole('ADMIN') or hasPermission(#departmentId, 'read')")

public List<User> getUsers(@PathVariable Long departmentId) {

return userService.getUsersByDepartmentId(departmentId);

}

}

  1. Configure Spring Security

@Configuration

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired

private CustomUserDetailsService customUserDetailsService;

@Autowired

private CustomPermissionEvaluator customPermissionEvaluator;

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/admin/**").hasRole("ADMIN")

.antMatchers(HttpMethod.GET, "/users/**").access("hasRole('ADMIN') or hasPermission(#departmentId, 'read')")

.antMatchers(HttpMethod.POST, "/users").access("hasRole('ADMIN') or hasPermission(#user.departmentId, 'write')")

.antMatchers(HttpMethod.PUT, "/users/**").access("hasRole('ADMIN') or hasPermission(#user.departmentId, 'write')")

.antMatchers(HttpMethod.DELETE, "/users/**").access("hasRole('ADMIN') or hasPermission(#user.departmentId, 'write')")

.and()

.formLogin()

.and()

.httpBasic()

.and()

.csrf().disable();

}

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.userDetailsService(customUserDetailsService);

}

@Override

public void configure(WebSecurity web) throws Exception {

DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();

handler.setPermissionEvaluator(customPermissionEvaluator);

web.expressionHandler(handler);

}

}

In the SecurityConfig configuration class, we use two custom services, CustomUserDetailsService and CustomPermissionEvaluator . Among them, CustomUserDetailsService is used to load user information, and CustomPermissionEvaluator is used to determine whether the user has specified permissions.

  1. Custom service

Finally, we also need to implement two custom services, CustomUserDetailsService and CustomPermissionEvaluator . The CustomUserDetailsService service is used to load user information from the database. In the CustomPermissionEvaluator service, we implement the hasPermission method, which is used to determine whether the current user has the specified permissions.

@Service

public class CustomUserDetailsService implements UserDetailsService {

@Autowired

private UserRepository userRepository;

@Override

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

User user = userRepository.findByUsername(username)

.orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));

List<SimpleGrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));

return new org.springframework.security.core.userdetails.User(user.getUsername(), "", authorities);

}

}

@Service

public class CustomPermissionEvaluator implements PermissionEvaluator {

@Autowired

private UserRepository userRepository;

@Override

public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {

if (targetDomainObject == null) {

return true;

}

Long departmentId = (Long) targetDomainObject;

User currentUser = userRepository.findByUsername(authentication.getName())

.orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + authentication.getName()));

if (currentUser.getDepartmentId() == null) {

return false;

}

if ("read".equals(permission)) {

return currentUser.getDepartmentId().equals(departmentId) || "ADMIN".equals(authentication.getAuthorities().iterator().next().getAuthority());

} else if ("write".equals(permission)) {

return currentUser.getDepartmentId().equals(departmentId) || "ADMIN".

Guess you like

Origin blog.csdn.net/heihei_100/article/details/129767693