美文网首页Springboot 系列
SpringBoot+shiro+mybatis实现权限登录

SpringBoot+shiro+mybatis实现权限登录

作者: Java旺 | 来源:发表于2020-11-20 17:48 被阅读0次

    SpringBoot+shiro+mybatis+Thymeleaf实现权限登录系统

    记录一下,学习shiro的一个小Demo:

    1.首先是底层数据库:

    -- ----------------------------
    -- Table structure for role
    -- ----------------------------
    CREATE TABLE `role`  (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色表主键',
      `role_name` varchar(32) DEFAULT NULL COMMENT '角色名称',
      PRIMARY KEY (`id`)
    );
    
    -- ----------------------------
    -- Records of role
    -- ----------------------------
    INSERT INTO `role` VALUES (1, 'SUPER_ADMIN');
    INSERT INTO `role` VALUES (2, 'ADMIN');
    INSERT INTO `role` VALUES (3, 'USER');
    
    -- ----------------------------
    -- Table structure for user
    -- ----------------------------
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user`  (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户主键',
      `username` varchar(32) NOT NULL COMMENT '用户名',
      `password` varchar(32) NOT NULL COMMENT '密码',
      `role_id` int(11) DEFAULT NULL COMMENT '与role角色表联系的外键',
      PRIMARY KEY (`id`),
      CONSTRAINT `user_role_on_role_id` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
    );
    
    -- ----------------------------
    -- Records of user
    -- ----------------------------
    INSERT INTO `user` VALUES (1, 'BWH_Steven', '666666', 1);
    INSERT INTO `user` VALUES (2, 'admin', '666666', 2);
    INSERT INTO `user` VALUES (3, 'zhangsan', '666666', 3);
    
    -- ----------------------------
    -- Table structure for permission
    -- ----------------------------
    CREATE TABLE `permission`  (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限表主键',
      `permission_name` varchar(50) NOT NULL COMMENT '权限名',
      `role_id` int(11) DEFAULT NULL COMMENT '与role角色表联系的外键',
      PRIMARY KEY (`id`),
      CONSTRAINT `permission_role_on_role_id` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
    );
    
    -- ----------------------------
    -- Records of permission
    -- ----------------------------
    INSERT INTO `permission` VALUES (1, 'user:*', 1);
    INSERT INTO `permission` VALUES (2, 'user:*', 2);
    INSERT INTO `permission` VALUES (3, 'user:queryAll', 3);
    

    2.创建spring boot项目,用maven构建

    创建实体类(User,Role,Permissions):

    User:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private Integer id;
        private String username;
        private String password;
        //用户对应的角色集合
        private Role role;
    }
    

    Role:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Role {
        private Integer id;
        private String roleName;
    }
    

    Permissions:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Permissions {
        private Integer id;
        private String permissionName;
        private Role role;
    }
    

    我们需要知道三个实体类之间的关系,User与Role一对一,Role与Permissions一对一,当然也可以把它都写成多对多,这就需要去更改数据库文件,和实体类了。

    3.在pom.xml添加相关依赖:

    下面只给出相关依赖源

    <dependency>
                <groupId>com.github.theborakompanioni</groupId>
                <artifactId>thymeleaf-extras-shiro</artifactId>
                <version>2.0.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.5.3</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.3</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    4.整合mybatis和springboot:

    就只需要创建一个dao层,一个服务层,需要记住要 添加注解

    (1)mapper配置文件(也可以使用注解形式):

    <?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.example.csy.dao.UserMapper">
    
        <select id="queryUserByUsername" resultMap="userRoleMap">
            SELECT u.*,r.role_name FROM `user` u, `role` r
              WHERE username = #{username} AND u.role_id = r.id;
        </select>
        <!-- 定义封装 User和 role 的 resultMap -->
        <resultMap id="userRoleMap" type="com.example.csy.entity.User">
            <id property="id" column="id"/>
            <result property="username" column="username"></result>
            <result property="password" column="password"></result>
            <!-- 配置封装 UserPojo 的内容 -->
            <association property="role" javaType="com.example.csy.entity.Role">
                <id property="id" column="id"></id>
                <result property="roleName" column="role_name"></result>
            </association>
        </resultMap>
    
        <select id="queryPermissionByUsername" resultMap="permissionRoleMap">
            SELECT p.* ,r.role_name FROM `user` u, `role` r, `permission` p
              WHERE username = #{username} AND u.role_id = r.id AND p.role_id = r.id;
        </select>
        <!-- 定义封装 permission 和 role 的 resultMap -->
        <resultMap id="permissionRoleMap" type="com.example.csy.entity.Permissions">
            <id property="id" column="id"/>
            <result property="permissionName" column="permission_name"></result>
            <!-- 配置封装 Role 的内容 -->
            <association property="role" javaType="com.example.csy.entity.Role">
                <id property="id" column="id"></id>
                <!--property是实体类中被赋值的参数名,column是数据库的列名-->
                <result property="roleName" column="role_name"></result>
            </association>
        </resultMap>
    </mapper>
    

    (2)DAO层:

    @Mapper
    public interface UserMapper {
        User queryUserByUsername(@Param("username") String username);
    
        Permissions queryPermissionByUsername(@Param("username") String username);
    }
    

    (3)service层:

    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public User queryUserByUsername(String username) {
    
            return userMapper.queryUserByUsername(username);
        }
    
        @Override
        public Permissions queryPermissionByUsername(String username) {
            return userMapper.queryPermissionByUsername(username);
        }
    }
    

    弄到这里,我们的mybatis+springboot整合也基本结束,所以在测试类里测试一下:

    @SpringBootTest
    class CsyApplicationTests {
    
        @Autowired
        private UserMapper userMapper;
    
        @Test
        void contextLoads() {
            User admin = userMapper.queryUserByUsername("admin");
            System.out.println(admin.toString());
            Permissions permission = userMapper.queryPermissionByUsername("admin");
            System.out.println(permission.toString());
        }
    }
    

    测试结果:

    得到了查询结果

    SpringBoot+shiro+mybatis实现权限登录

    6.整合Thymeleaf进来:

    前端页面:

    在html页面我们整合了Thymeleaf,使用了Jquery,semantic,需要导包

    SpringBoot+shiro+mybatis实现权限登录 SpringBoot+shiro+mybatis实现权限登录

    index.html代码:

    在这里,如果是User就只能访问A,Admin能访问A,B,superAdmin能访问A,B,C

    <!DOCTYPE html>
    <html lang="zh_CN"
          xmlns:th="http://www.thymeleaf.org"
          xmlns="http://www.w3.org/1999/xhtml"
          xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
          xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
    >
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>信息管理平台-首页</title>
        <meta
                name="viewport"
                content="width=device-width, initial-scale=1, maximum-scale=1"
        />
        <title>首页</title>
        <!--semantic-ui-->
        <link
                href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css"
                rel="stylesheet"
        />
    
        <!--<link href="css/index.css" rel="stylesheet">-->
        <link th:href="@{/css/index.css}" rel="stylesheet">
    
        <!-- <script th:src="@{js/jquery-3.1.1.min.js}"></script> -->
        <script src="js/jquery-3.1.1.min.js"></script>
    </head>
    <body>
    <div class="ui container">
        <div class="ui secondary menu">
            <a class="active item" th:href="@{/index}">
                首页
            </a>
    
            <a class="active item" th:href="@{/about}">
                关于
            </a>
            <!--登录注销-->
            <div class="right menu">
    
                <!--如果未登录-->
                <!--<div shiro:authorize="!isAuthenticated()">-->
                <div shiro:notAuthenticated="">
                    <a class="item" th:href="@{/toLoginPage}">
                        <i class="address card icon"></i> 登录
                    </a>
                </div>
    
                <!--如果已登录-->
                <div shiro:authenticated="">
                    <a class="item">
                        <i class="address card icon"></i>
                        用户名:<span shiro:principal></span>
                        <!--角色:<span sec:authentication="principal.authorities"></span>-->
                    </a>
                </div>
    
                <div shiro:authenticated="">
                    <a class="item" th:href="@{/logout}">
                        <i class="address card icon"></i> 注销
                    </a>
                </div>
            </div>
        </div>
    
        <div class="ui stackable three column grid">
            <div class="column" shiro:hasAnyRoles="USER,ADMIN,SUPER_ADMIN"><!--有其中任一一个角色课访问-->
                <div class="ui raised segments">
                    <div class="ui segment">
                        <a th:href="@{/levelA/a}">L-A-a</a>
                    </div>
                    <div class="ui segment">
                        <a th:href="@{/levelA/b}">L-A-b</a>
                    </div>
                    <div class="ui segment">
                        <a th:href="@{/levelA/c}">L-A-c</a>
                    </div>
                </div>
            </div>
            <div class="column" shiro:hasAnyRoles="ADMIN,SUPER_ADMIN">
                <div class="ui raised segments">
                    <div class="ui segment">
                        <a th:href="@{/levelB/a}">L-B-a</a>
                    </div>
                    <div class="ui segment">
                        <a th:href="@{/levelB/b}">L-B-b</a>
                    </div>
                    <div class="ui segment">
                        <a th:href="@{/levelB/c}">L-B-c</a>
                    </div>
                </div>
            </div>
            <div class="column" shiro:hasRole="SUPER_ADMIN">
                <div class="ui raised segments">
                    <div class="ui segment">
                        <a th:href="@{/levelC/a}">L-C-a</a>
                    </div>
                    <div class="ui segment">
                        <a th:href="@{/levelC/b}">L-C-b</a>
                    </div>
                    <div class="ui segment">
                        <a th:href="@{/levelC/c}">L-C-c</a>
                    </div>
                </div>
            </div>
            <!-- <div class="column"></div> -->
        </div>
    
        <div class="ui stacked segment">
            <div class="ui stackable three column grid">
                <div class="column">
                    <p>
                        晚风吹起你鬓间的白发<br/>
                        抚平回忆留下的疤<br/>
                        你的眼中 明暗交杂 一笑生花<br/>
                        暮色遮住你蹒跚的步伐<br/>
                        走进床头藏起的画<br/>
                        画中的你 低着头说话<br/>
                        我仍感叹于世界之大
                    </p>
                </div>
    
                <div class="column">
                    <p>
    
                        也沉醉于儿时情话<br/>
                        不剩真假 不做挣扎 无谓笑话<br/>
                        我终将青春还给了她<br/>
                        连同指尖弹出的盛夏<br/>
                        心之所动 就随风去了<br/>
                        以爱之名 你还愿意吗<br/>
                        ❤
                    </p>
                </div>
                <div class="column">
                    <img class="ui medium circular image" src="images/001.jpg">
                </div>
            </div>
    
        </div>
    
        <div class="ui info message">
            <div class="header">理想二旬不止</div>
            <p>BWH_Steven</p>
        </div>
    </div>
    
    </body>
    </html>
    

    login.html代码:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org"
          xmlns="http://www.w3.org/1999/xhtml"
          xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
    >
    <head>
        <meta charset="UTF-8">
        <title>用户管理系统-登录</title>
        <!-- <script th:src="@{js/jquery-3.1.1.min.js}"></script> -->
        <script src="js/jquery-3.1.1.min.js"></script>
        <link
                href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css"
                rel="stylesheet"
        />
    </head>
    <body>
    <h1>用户管理系统-登录</h1>
    <div class="ui container" style="margin-top: 180px;">
        <div style="text-align: center; margin-bottom: 20px;">
            <h1 class="header">
                登录
            </h1>
        </div>
    
        <div class="ui three column stackable grid login-div">
            <div class="column"></div>
            <div class="column">
                <form id="login" class="ui fluid form segment" th:action="@{/login}" method="post">
                    <div class="field">
                        <label class="">用户名</label>
                        <div class="ui left icon input">
                            <input type="text" name="username" placeholder=""/>
                            <i class="user icon"></i>
                            <div class="ui corner label">
                                <i class="icon asterisk"></i>
                            </div>
                        </div>
                    </div>
                    <div class="field">
                        <label class="">密码</label>
                        <div class="ui left icon input">
                            <input type="password" name="password" placeholder=""/>
                            <i class="lock icon"></i>
                            <div class="ui corner label">
                                <i class="icon asterisk"></i>
                            </div>
                        </div>
                    </div>
                    <div class="inline field">
                        <div class="ui checkbox">
                            <input type="checkbox" name="terms"/>
                            <label>记住密码</label>
                        </div>
                    </div>
                    <div class="inline field">
                        <input type="submit" class="ui blue submit button">
                    </div>
                </form>
            </div>
            <div class="column"></div>
        </div>
    </div>
    
    </body>
    </html>
    

    success.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户管理系统-成功</title>
    </head>
    <body>
    <h2>登录成功</h2>
    <a href="/index">返回主页</a>
    </body>
    </html>
    

    7.将shiro整合到项目里:

    (1)自定义Realm:

    我们需要自定义,认证和授权:

    public class UserRealm extends AuthorizingRealm {
    
        @Autowired
        private UserMapper userMapper;
    
        /**
         * @MethodName doGetAuthorizationInfo 授权操作
         * @Description 权限配置类
         * @Param [principalCollection]
         * @Return AuthorizationInfo
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            // 获取用户名信息
            String username = (String) principalCollection.getPrimaryPrincipal();
            // 创建一个简单授权验证信息
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            // 给这个用户设置从 role 表获取到的角色信息
            authorizationInfo.addRole(userMapper.queryUserByUsername(username).getRole().getRoleName());
            //给这个用户设置从 permission 表获取的权限信息
            authorizationInfo.addStringPermission(userMapper.queryPermissionByUsername(username).getPermissionName());
            return authorizationInfo;
        }
    
        /**
         * @MethodName doGetAuthenticationInfo 身份验证
         * @Description 认证配置类
         * @Param [authenticationToken]
         * @Return AuthenticationInfo
         * @Author WangShiLin
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            // 根据在接受前台数据创建的 Token 获取用户名
            String username = (String) authenticationToken.getPrincipal();
    
    //        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
    //        System.out.println(userToken.getPrincipal());
    //        System.out.println(userToken.getUsername());
    //        System.out.println(userToken.getPassword());
    
            // 通过用户名查询相关的用户信息(实体)
            User user = userMapper.queryUserByUsername(username);
            if (user != null) {
                // 存入 Session,可选
                SecurityUtils.getSubject().getSession().setAttribute("user", user);
                // 密码认证的工作,Shiro 来做
                AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), "userRealm");
                return authenticationInfo;
            } else {
                // 返回 null 即会抛异常
                return null;
            }
        }
    }
    

    (2)写配置类shiroConfig:

    @Configuration
    public class ShiroConfig {
    
        //将自己的验证方式加入容器
        @Bean
        public UserRealm myShiroRealm() {
            return new UserRealm();
        }
    
        /**
         * 配置安全管理器 SecurityManager
         *
         * @return
         */
        @Bean
        public DefaultWebSecurityManager securityManager() {
            // 将自定义 Realm 加进来
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 关联 Realm
            securityManager.setRealm(myShiroRealm());
            return securityManager;
        }
    
        /**
         * 配置 Shiro 过滤器
         *
         * @param securityManager
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
            // 定义 shiroFactoryBean
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    
            // 关联 securityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            // 自定义登录页面,如果登录的时候,就会执行这个请求,即跳转到登录页
            shiroFilterFactoryBean.setLoginUrl("toLoginPage");
            // 指定成功页面
            shiroFilterFactoryBean.setSuccessUrl("/success");
            // 指定未授权界面
            shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
    
            // 设置自定义 filter
            Map<String, Filter> filterMap = new LinkedHashMap<>();
            filterMap.put("anyRoleFilter", new MyRolesAuthorizationFilter());
            shiroFilterFactoryBean.setFilters(filterMap);
    
            // LinkedHashMap 是有序的,进行顺序拦截器配置
            Map<String, String> filterChainMap = new LinkedHashMap<>();
    
            // 配置可以匿名访问的地址,可以根据实际情况自己添加,放行一些静态资源等,anon 表示放行
            filterChainMap.put("/css/**", "anon");
            filterChainMap.put("/img/**", "anon");
            filterChainMap.put("/js/**", "anon");
            // 指定页面放行,例如登录页面允许所有人登录
            filterChainMap.put("/toLoginPage", "anon");
    
            // 以“/user/admin” 开头的用户需要身份认证,authc 表示要进行身份认证
            filterChainMap.put("/user/admin/**", "authc");
    
            // 页面 -用户需要角色认证
            filterChainMap.put("/levelA/**", "anyRoleFilter[USER,ADMIN,SUPER_ADMIN]");
            filterChainMap.put("/levelB/**", "anyRoleFilter[ADMIN,SUPER_ADMIN]");
            filterChainMap.put("/levelC/**", "anyRoleFilter[SUPER_ADMIN]");
    
    //        filterChainMap.put("/levelA/**", "roles[USER]");
    //        filterChainMap.put("/levelB/**", "roles[ADMIN]");
    //        filterChainMap.put("/levelC/**", "roles[SUPER_ADMIN]");
    
            // /user/admin/ 下的所有请求都要经过权限认证,只有权限为 user:[*] 的可以访问,也可以具体设置到 user:xxx
            filterChainMap.put("/user/admin/**", "perms[user:*]");
    
            // 配置注销过滤器
            filterChainMap.put("/logout", "logout");
    
            // 将Map 存入过滤器
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
            return shiroFilterFactoryBean;
        }
    
        /**
         * 整合 thymeleaf
         * @return
         */
        @Bean(name = "shiroDialect")
        public ShiroDialect shiroDialect(){
            return new ShiroDialect();
    
        }
    

    首先我们将自定义的Realm方法,依赖注入进来到容器

    //将自己的验证方式加入容器
        @Bean
        public UserRealm myShiroRealm() {
            return new UserRealm();
        }
    

    然后是:SecurityManager配置安全管理器

    /**
         * 配置安全管理器 SecurityManager
         *
         * @return
         */
        @Bean
        public DefaultWebSecurityManager securityManager() {
            // 将自定义 Realm 加进来
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 关联 Realm
            securityManager.setRealm(myShiroRealm());
            return securityManager;
        }
    

    最后就是自定义的过滤器,控制那些页面需要什么样的角色才能访问,哪些资源需要谁才能访问,并且setSecurityManager,返回一个ShiroFilterFactoryBean。

    重点说一下拦截放行(Map)这块:通过 map 键值对的形式存储,key 存储 URL ,value 存储对应的一些权限或者角色等等,其实 key 这块还是很好理解的,例如 :/css/、/user/admin/ 分别代表 css 文件夹下的所有文件,以及请求路径前缀为 /user/admin/ URL,而对应的 value 就有一定的规范了。

    关键:

    anon:无需认证,即可访问,也就是游客也可以访问

    authc:必须认证,才能访问,也就是例如需要登录后

    roles[xxx] :比如拥有某种角色身份才能访问 ,注:xxx为角色参数

    perms[xxx]:必须拥有对某个请求、资源的相关权限才能访问,注:xxx为权限参数

    (3)自定义一个角色认证过滤器MyRolesAuthorizationFilter:

    因为我们的角色,只需用有一个角色就能访问到映射页面,shiro默认是hasAllRoles,也就是说,我们要满足所有的身份才能访问,所以需要我们自定义一个hasAnyRoles,任选其一角色即可。

    public class MyRolesAuthorizationFilter extends AuthorizationFilter {
    
        @SuppressWarnings({"unchecked"})
        public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
    
            Subject subject = getSubject(request, response);
            String[] rolesArray = (String[]) mappedValue;
    
            if (rolesArray == null || rolesArray.length == 0) {
                //no roles specified, so nothing to check - allow access.
                return false;
            }
    
            List<String> roles = CollectionUtils.asList(rolesArray);
            boolean[] hasRoles = subject.hasRoles(roles);
            for (boolean hasRole : hasRoles) {
                if (hasRole) {
                    return true;
                }
            }
            return false;
        }
    }
    

    (4)最后就是controller

    controller是springMvc的前端控制器,接收什么请求,并且返回对应指定的页面(映射)。

    首先我们先将所以页面的映射写好,

    PageController:

    @Controller
    public class PageController {
    
        @RequestMapping({"/", "index"})
        public String index() {
            return "index";
        }
    
        @RequestMapping("about")
        public String toAboutPage() {
            return "redirect:http://www.ideal-20.cn";
        }
    
        @RequestMapping("/toLoginPage")
        public String toLoginPage() {
            return "views/login";
        }
    
        @RequestMapping("/levelA/{name}")
        public String toLevelAPage(@PathVariable("name") String name) {
            return "views/L-A/" + name;
        }
    
        @RequestMapping("/levelB/{name}")
        public String toLevelBPage(@PathVariable("name") String name) {
            return "views/L-B/" + name;
        }
    
        @RequestMapping("/levelC/{name}")
        public String toLevelCPage(@PathVariable("name") String name) {
            return "views/L-C/" + name;
        }
    
        @RequestMapping("/unauthorized")
        public String toUnauthorizedPage() {
            return "views/unauthorized";
        }
    
        @RequestMapping("/success")
        public String toSuccessPage() {
            return "views/success";
        }
    
    }
    

    UserController:

    上面那两个映射,只是测试,主要是那个login方法,他可以根据我们前台输入的数据,并创建一个token,如果该token能被认证,即返回成功页面,否则就失败。

    @Controller
    public class UserController {
        @RequestMapping("/user/queryAll")
        @ResponseBody
        public String queryAll() {
            return "这是 user/queryAll 方法";
        }
    
        @RequestMapping("/user/admin/add")
        @ResponseBody
        public String adminAdd() {
            return "这是 user/adminAdd 方法";
        }
    
        @RequestMapping("/login")
        public String login(String username, String password, HttpServletRequest request) {
            // 由于是根据name参数获取的,我这里封装了一下
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
    
            // 创建出一个 Token 内容本质基于前台的用户名和密码(不一定正确)
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            // 获取 subject 认证主体(这里也就是现在登录的用户)
            Subject subject = SecurityUtils.getSubject();
            try{
                // 认证开始,这里会跳转到自定义的 UserRealm 中
                subject.login(token);
                // 可以存储到 session 中
                request.getSession().setAttribute("user", user);
                return "views/success";
            }catch(Exception e){
                // 捕获异常
                e.printStackTrace();
                request.getSession().setAttribute("user", user);
                request.setAttribute("errorMsg", "兄弟,用户名或密码错误");
                return "views/login";
            }
        }
    }
    

    8.最终效果:

    首先是 http://localhost :8080/index

    SpringBoot+shiro+mybatis实现权限登录

    登录界面:

    SpringBoot+shiro+mybatis实现权限登录

    表单提交后,就返回值到UserController那个Login方法,认证:

    SpringBoot+shiro+mybatis实现权限登录

    这样我们就登录成功了,并且是superAdmin的权限,可以查看A,B,C

    SpringBoot+shiro+mybatis实现权限登录

    而用户张三,只能看见A

    SpringBoot+shiro+mybatis实现权限登录

    来源:https://www.tuicool.com/articles/RBzueij

    相关文章

      网友评论

        本文标题:SpringBoot+shiro+mybatis实现权限登录

        本文链接:https://www.haomeiwen.com/subject/yrqriktx.html