Spring Security实践

好的,这里简单举个例子,演示如何使用Spring Security实现基于角色的数据权限控制。

首先,在Spring Security中,可以使用@PreAuthorize注解来进行数据权限控制的配置。@PreAuthorize注解可以用于在方法调用之前对参数进行权限校验,如果权限校验不通过,则会抛出异常。

  1. 创建实体类和数据访问层

首先,我们创建一个User实体类和一个UserRepository数据访问层。User实体类中包含了一个username字段和一个departmentId字段,用于表示用户的账号名和所属部门。UserRepository数据访问层提供了一个findByDepartmentId方法,用于根据部门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. 创建服务层

接着,我们创建一个UserService服务层,用于提供用户信息的查询服务。在UserService服务层中,我们定义了一个getUsersByDepartmentId方法,该方法用于根据部门ID获取该部门下的所有用户信息。在方法中,我们首先获取当前登录用户的角色和部门信息,然后根据当前登录用户的角色和部门信息对返回的用户列表进行过滤,只返回符合条件的用户信息。

@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. 创建控制器

最后,我们创建一个UserController控制器,用于提供用户信息查询的接口。在UserController控制器中,我们使用@PreAuthorize注解对接口进行权限控制的配置。只有拥有ADMIN角色或者对应用户具有读取权限的用户才能访问该接口。

@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. 配置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);

}

}

SecurityConfig配置类中,我们使用了CustomUserDetailsServiceCustomPermissionEvaluator两个自定义的服务。其中,CustomUserDetailsService用于加载用户信息,CustomPermissionEvaluator用于判断用户是否有指定权限。

  1. 自定义服务

最后,我们还需要实现CustomUserDetailsServiceCustomPermissionEvaluator两个自定义服务。CustomUserDetailsService服务用于从数据库中加载用户信息。在CustomPermissionEvaluator服务中,我们实现了hasPermission方法,该方法用于判断当前用户是否有指定权限。

@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".

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值