【SpringSecurity】SpringSecurity安全框架授权

授权

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

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

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

首先开启相关配置。

java 复制代码
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // ......
}

使用对应的注解。@PreAuthorize

java 复制代码
@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,让其能封装权限信息。

java 复制代码
@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;
    }
    // 其他方法......
}
java 复制代码
@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());

java 复制代码
@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);
    }
}

分别调用接口运行测试

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

从数据库查询权限信息

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

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

相关推荐
lkbhua莱克瓦2413 小时前
反射4-反射获取成员变量
java·开发语言·servlet·反射
lifewange13 小时前
Linux 日志查看命令速查表
java·linux·运维
风景的人生13 小时前
一台电脑上可以同时运行多个JVM(Java虚拟机)实例
java·开发语言·jvm
阿蒙Amon14 小时前
C#每日面试题-进程和线程的区别
java·面试·c#
一 乐14 小时前
养老院信息|基于springboot + vue养老院信息管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
hopsky14 小时前
mvn install 需要 手动清除 pom.lastUpdated
java·maven·mavbne
59803541514 小时前
【java工具类】小数、整数转中文小写
android·java·开发语言
cike_y14 小时前
Mybatis之作用域(Scope)和生命周期-解决属性名和字段名不一致的问题&ResultMap结果集映射
java·开发语言·数据库·tomcat·mybatis
天远Date Lab14 小时前
构建金融级信贷审批系统:Java Spring Boot 集成天远借贷行为验证 API 全指南
java·大数据·spring boot·金融
虾说羊14 小时前
transferManager为什么在工作中禁止使用 (怎么进行优化 怎么避免多线程的堵塞)
java·服务器·数据库