Bootstrap

【SpringSecurity】SpringSecurity安全框架授权

授权

权限系统要实现的效果:不同的用户可以使用不同的功能

在后台进行用户权限的判断,判断当前用户是否有相应的权限,必须具有所需权限才能进行相应的操作。

在 SpringSecurity 中,默认使用 FilterSecurityInterceptor 进行权限校验。在 FilterSecurityInterceptor 中会从SecurityContextHolder 获取其中的 Authentication,然后获取其中的权限信息。当前用户是否拥有访问当前资源所需的权限。所以我们在项目中只需要把当前登录用户的权限信息也存入 Authentication,然后设置我们的资源所需要的权限即可。

首先开启相关配置。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // ......
}

使用对应的注解。@PreAuthorize

@RestController
@RequestMapping("/user")
public class SysUserController {
    @Resource
    private SysUserService sysUserService;
    // 登录方法......
    // 退出登录......
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('USER1')")
    public ResultJSON list() {
        return ResultJSON.success();
    }
}

封装权限信息

写 UserDetailsServiceImzho 中,在查询出用户后还要获取对应的权限信息,封装到 UserDetails 中返回。

把权限信息写死封装到 UserDetails 中进行测试。

修改 UserDetails 的实现类 LoginUser,让其能封装权限信息。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements UserDetails {
    private SysUser sysUser;
    private List<String> permissions;

    public LoginUser(SysUser sysUser, List<String> permissions) {
        this.sysUser = sysUser;
        this.permissions = permissions;
    }
    //存储SpringSecurity所需要的权限信息的集合
    @JSONField(serialize = false)
    private List<GrantedAuthority> authorities;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (authorities != null) {
            return authorities;
        }
        authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",",permissions));
        return authorities;
    }
    // 其他方法......
}
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Resource
    private SysUserDao sysUserDao;
    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        // 根据用户名查询用户信息
        SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>()
                .eq("user_name", username));
        if (Objects.isNull(sysUser)) {
            throw new RuntimeException("用户名或密码错误");
        }
        // 从数据库中获取权限列表
        List<String> list = new ArrayList<>;
        list.add("USER1");
        // list.add("USER2");
        // 返回用户信息 和 权限集合
        return new LoginUser(sysUser, list);
    }
}

在 JwtAuthenticationTokenFilter 中修改如下代码

UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Resource
    private RedisCache redisCache;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //......
        //存入SecurityContextHolder
        //TODO 获取权限信息封装到Authentication中
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行
        filterChain.doFilter(request, response);
    }
}

分别调用接口运行测试

@RestController
@RequestMapping("/user")
public class SysUserController {
    @Resource
    private SysUserService sysUserService;
    // 登录方法......
    // 退出登录......
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('USER1')")
    public ResultJSON list() {
        return ResultJSON.success();
    }
}
@RestController
@RequestMapping("/order")
public class SysOrderController {
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('USER2')")
    public ResultJSON list() {
        return ResultJSON.success();
    }
}

从数据库查询权限信息

RBAC 权限模型(Role-Based Access Control)

基于角色的权限控制。这是目前最常被开发者使用也是相对易用、通用权限模型。

在这里插入图片描述

;