• SpringBoot 18 Shiro实现登陆拦截和用户认证


    18.1 实现登陆拦截


    实现登陆拦截:意思是说,我们访问 某个页面的时候,必须要 给这个页面赋予 一个 过滤器。让它来决定我们 是否能够访问,而当不能访问的时候,则跳转到一个登陆的页面。这就是登陆拦截。

    shiro 的内置过滤器有 大概五种:

    • anon:无需认证就可以访问
    • authc:必须认证 才能访问
    • user:必须 选择 记住我 功能 才可以
    • perms:拥有某个资源的权限才能访问
    • role:拥有某个角色权限才能访问

    比如我们 现在 做一个 authc,必须通过 认证 才能访问 页面的功能。

        @Bean(name = "shiroFilterFactoryBean")
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            bean.setSecurityManager(defaultWebSecurityManager);
    
    		// 设置过滤链,可以 拿 一个 链式 Map,所以我们新建一个 链式 Map
            Map<String,String> filterMap = new LinkedHashMap<>();
            // 这两个页面 都 必须通过 认证才能访问
            filterMap.put("/user/add","authc");
            filterMap.put("/user/update","authc");
            bean.setFilterChainDefinitionMap(filterMap);
    
            // Shiro 没有默认提供给你的 登录页面,得自己去写
            // 设置 登录 界面的 url 是什么,这样的话,我们一旦 被过滤器不允许访问 页面,就会 自动的 跳转到 登录页。
            bean.setLoginUrl("/toLogin");
    
            return bean;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    登录页

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
    <h1>登录h1>
    <form th:action="@{/login}" method="post">
        <p>用户名:<input type="text" name="username">p>
        <p>密码:<input type="text" name="password">p>
        <p><input type="submit" value="登录">p>
    form>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    18.2 用户认证

    编写 登录 需要的 Controller

    @RequestMapping("/login")
        public String login(String username, String password, Model model){
            // 获取到 subject
            Subject subject = SecurityUtils.getSubject();
            // 把 username 和 password 封装成 一个 登录 token
    
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
    
            try {
                subject.login(usernamePasswordToken);
                model.addAttribute("msg","登录成功");
                return "index";
            }catch (UnknownAccountException e){
                model.addAttribute("msg","用户名错误");
                return "login";
            }catch (IncorrectCredentialsException e){
                model.addAttribute("msg","密码错误");
                return "login";
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    当我们 运行之后,我们就会发现,它 在 login() 的时候,会 去走 User Realm 的认证那个方法。

    在这里插入图片描述
    那也就是说,我们 的 login() 认证 实际上 还需要 我们 自己去写一下。也就是 我们 要在 认证那个 方法里面写一些 东西。

    在这里插入图片描述
    首先我们发现,这个地方 有一个 参数,正好 也是 Token。所以我们 可以 很好的理解为,它是 我们 login() 登录的时候,传递过来的 那个 token 令牌。那么就好办了,我们只需要 做一个 伪数据,进行 判断 即可实现 认证。

        // 认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("执行了认证");
    
            String name = "root";
            String password = "123";
    
            UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
            if(!token.getUsername().equals(name)){
                return null;// 这样的写法 会自动 抛出 异常 UnknowAccountException
            }
            // 密码认证,shiro 不让我们 开发者去做。它帮我们做。所以不用写
    
            return new SimpleAuthenticationInfo("",password,"");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 这个认证方法是要 返回 一个 认证信息对象的。我们观察这个对象,发现第二个参数说的是 资格证书,其实 大概就是我们的密码。Shiro不建议我们 自己 去做 密码的 认证。所以我们大可 把 密码传递给它。让它去帮我们做。那么有的人就会问了,用户有多个呀,密码肯定也有多个,你怎么保证传递的这个密码就肯定 是一一对应的呢?答:可以通过拿到的token去判断传递的正确密码是啥。
    • return null; 在 判断 用户名是否一致的时候,如果 返回了 null,那么实际上 它 是给你 自动抛出了 异常 UnknowAccountException

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    PHP使用 FormBuilder 创建表单
    前端vue实现目录锚点跳转及滚动到指定内容区域(带源码)
    Windows10神州网信政府版的配置修改
    ubuntu apt工具软件操作
    Ceph入门到精通-sysctl参数优化
    二维码智慧门牌管理系统升级解决方案:运营可视化之道
    linux软硬连接
    Java内部类分类
    lvm删除分区、扩容分区
    洛谷C++简单题小练习day11—字母转换,分可乐两个小程序
  • 原文地址:https://blog.csdn.net/qq_52606908/article/details/126132965