如何实现登录后只显示自己信息的页面_Springboot Shiro页面按钮显示、路径越权访问题...

阅读前文章

SpringBoot Shiro 实现登录/记住我的功能

SpringBoot Shiro基于Url权限拦截系统

本文导读

通过以上两篇文章,已经实现了shiro登录,基于Url实现权限拦截,那么问题来了,现在有需求要求:用户登录后进入主页或者某个页面,只显示这个用户拥有的权限菜单、按钮,无权限不应该显示。针对这个需求,我们应该如何处理呢?这就是本文重点实现的。

编写SQL/DAO/Controller都是使用前面两篇文章代码。

如何控制显示‘查询按钮’权限?

这个时候我们需要用shiro标签,这个也是shiro整合好thymeleaf实现的,我们现在只需要实现进入主页,根据用户显示对应的菜单权限按钮即可,其他功能按照此方法实现即可,代码如下

管理主页欢迎来到后台管理系统
您好: 退出登录

系统用户管理系统角色管理系统功能管理

shiro:hasPermission 标签的name属性值sysuser:list就是代表用户是否拥有这个权限,如果拥有,就会放开标签里面的内容进行显示。

那么这个是如何工作的呢?我们还需要继续编写代码。

去除掉自定义过滤器配置

如果你的项目实现了我们之前基于Url实现拦截系统,那么我们必须要把这个自定义过滤器移除配置,如果没有实现,可以忽略这个步骤,移除代码如下图

609dd536c64024c322379323ad8eb77d.png

移除自定义Url过滤器

修改SysUserRealm

把继承类AuthenticatingRealm改成AuthorizingRealm,同时实现doGetAuthorizationInfo授权功能方法,具体完成代码如下

/** * Realm域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份
* 1、那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法
* 2、需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作
*/@Slf4j@Configuration public class SysUserRealm extends AuthorizingRealm{//更改继承类AuthenticatingRealm -->AuthorizingRealm@AutowiredSysUserService sysUserService;@AutowiredSysActionDAO sysActionDAO;/** * 身份认证 / 登录,验证用户是不是拥有相应的身份
* SecurityUtils.getSubject().login()执行后--->进入这个方法执行具体登录校验
* */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//得到用户密码token凭证UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken)token;//获得登录用户名,密码String userName=usernamePasswordToken.getUsername();log.info("登录授权,username={}",userName);//根据用户名查询用户对象SysUserPO sysUserPO=new SysUserPO();sysUserPO.setUsername(userName);sysUserPO=sysUserService.get(sysUserPO);//如果等于null,说明用户不存在。//问题如何返回用户提示不存在呢?if(sysUserPO==null) {//通过抛出异常来解决提示错误信息throw new UnknownAccountException("用户不存在=".concat(userName));//自定义抛出异常,如果不是AuthenticationException子类,那么异常信息不会向上抛出,因此自定义异常要继承这个类,Shiro提供的默认异常基本够用了//throw new RuntimeException("用户不存在");}//如果账号状态是禁用状态if(new Integer(0).equals(sysUserPO.getStatus())){throw new DisabledAccountException("用户被禁用=".concat(userName));}//账号正常,校验登录密码//第一个参数,存返回用户对象,第二个参数存密码,第三个登录用户名SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(sysUserPO, sysUserPO.getPassword(), sysUserPO.getUsername());//返回登录授权信息,shiro会自动校验转入的密码与数据库返回的密码是否一致,如果一致,代表登录成功return simpleAuthenticationInfo;}/** * 授权权限,根据用户查询数据库对应的权限标识,把权限标识返回给shiro,shiro会自动做权限校验,成功就放行,错误就抛出异常 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//获取登录对象SysUserPO sysUserPO=(SysUserPO)principals.getPrimaryPrincipal();//根据用户查询拥有权限List permissionList=sysActionDAO.getListByUserId(sysUserPO.getId());SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();for (SysActionPO sysActionPO:permissionList) {//设置返回数据库权限info.addStringPermission(sysActionPO.getPermissions());} log.info("用户={},拥有权限={}",sysUserPO.getUsername(),info.getStringPermissions()); //最后把数据库权限信息返回到shiro中,shiro会自动与设置的权限进行校验,如果相等就授权通过,否则抛出授权认证异常return info;}}
fbde5d4f4586a777b432c0fad8299729.png

修改继承类

cf67aedfd938b1d27d615272ee417313.png

实现授权方法

数据表数据

编辑permissions字段权限标识字段,输入对应页面shiro:hasPermission 标签的name属性值sysuser:list,其他功能同理加入即可。如下图

6ac6e150602f810611d458867678efb7.png

权限标识字段

启动服务

通过测试账号,登录后,查询到权限列表,只拥有系统用户管理权限,其他权限都没有显示,达到我们的需求。

6c3f989e08b5e2a37def777532fead02.png

显示权限按钮

虽然上面我们控制了菜单显示,但是如果我们能猜想知道别的菜单权限路径,我们一访问,还是可以正常访问的,比如‘系统角色管理’,如下访问

直接通过浏览器访问:系统角色管理,还是可以访问,这个是不应该被允许http://127.0.0.1:7010/sysrole/list

如何解决越权操作呢?

很简单,这个也是shiro提供的一个注解RequiresPermissions,加上注解且把‘标识名称’写上且同数据库一样的就可以了,只要数据库有这个标识,且查询出来的标识跟这个标识一样,就可以访问,否则不可以访问,代码如下

/** * 系统角色 */@Controller@Slf4j@RequestMapping("sysrole")public class SysRoleController {/**  *   列表 */@GetMapping("list")//基于权限注解配置,最好以:隔开sysrole:list@RequiresPermissions("sysrole:list")public String list(HttpServletRequest request){SysRolePO sysRolePO=new SysRolePO();QueryWrapper queryWrapper=new QueryWrapper(sysRolePO);List sysUserPOs=sysRoleDAO.selectList(queryWrapper);request.setAttribute("pos", sysUserPOs);return "sysrole/list";}  }------/** * 系统用户控制器 */@Controller@Slf4j@RequestMapping("sysuser")public class SysUserController {  /**  *   列表 */@GetMapping("list")//基于权限注解配置,最好以:隔开sysuser:list@RequiresPermissions("sysuser:list")public String list(HttpServletRequest request){SysUserPO sysUserPO=new SysUserPO();QueryWrapper queryWrapper=new QueryWrapper(sysUserPO);List sysUserPOs=sysUserDAO.selectList(queryWrapper);request.setAttribute("sysUserPOs", sysUserPOs);return "sysuser/list";}}

重启服务,再次重新测试就可以解决越权操作了。

如果非法越权访问权限的时候,可能出现访问页面不进入授权页面,抛出如下异常

b38d29b6dc1a4538ed6996a0b083a3b4.png

异常

这个是因为shiro抛出了一个UnauthorizedException异常,在springboot里面就往外抛出了,导致进入不了无权限提示页面,那么我们就手动捕获这个异常,然后返回到指定无授权页面即可。如下代码

/** * 公共异常帮助类 */@RestControllerAdvice@Slf4jpublic class AdminExceptionHandler {/**    * 无权限访问,403错误     */    @ExceptionHandler(value = {UnauthorizedException.class})    public Object exceptionHandler(UnauthorizedException e,HttpServletRequest req,HttpServletResponse response) throws Exception {    log.error("请求URI={},系统内部异常={}",req.getRequestURI(),e);    if(AjaxUtils.isAjaxReq(req)){//如果ajax请求    return ResponseVO.fail("403","无权限访问");    }else{    return new ModelAndView("error/notAuth");    }    }}

路径访问图解流程

eeb01bcd4d0ee4c3ec3fbe30e9c70238.png

流程1

3c49a898521cbe32cbdbee09daa97811.png

流程2

4954a5200cd4e117b774cc5bbd368bb4.png

无权限异常

按钮显示图解流程

17ca050f500e88e89dc8a57b931d4111.png

流程

总结

本文已基本实现了对"菜单功能",非法越权访问,Shiro对这些功能很好的实现了,代码也很简单,如对本文流程不清楚的,欢迎大家讨论。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值