小工具知识网

当前位置: 首页 > 行业知识 > SpringBoot与Shiro整合

行业知识

SpringBoot与Shiro整合

2026-10-21 18:43:43 来源:互联网转载

一,Shiro 体系结构

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

  • Authentication 认证 ---- 用户登录
  • Authorization 授权 ---- 用户具有哪些权限
  • Cryptography 安全数据加密
  • Session Management 会话管理
  • Web Integration web系统集成
  • Interations 集成其它应用,spring、缓存框架

    二,构建spring boot工程

    建立Maven项目

    修改pom.xml

    • 继承Spring Boot 父工程
              org.springframework.boot        spring-boot-starter-parent        2.5.3            
      • 添加web支持
            org.springframework.boot    spring-boot-starter-web

        编写spring Boot启动类

        package com.example;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * @Description: SpringBoot启动类 */@SpringBootApplicationpublic class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }}

        编写测试Controller类

        package com.example.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;/** * @Description:控制层 */@Controllerpublic class TestController {    /**     * 测试方法     */    @GetMapping("/hello")    @ResponseBody    public String hello(){        System.out.println("UserController.hello()");        return "ok";    }}

        启动,测试

        三,引入thymeleaf页面模块

        修改pom.xml

        • 添加thymeleaf依赖
               org.springframework.boot     spring-boot-starter-thymeleaf 

          在Controller添加测试方法

          /**     * 测试thymeleaf     */    @RequestMapping("/test")    public String testThymeleaf(Model model){        //把数据存入model        model.addAttribute("name", "张三");        //返回test.html        return "test";    }

          建立test.html页面

          • 在src/main/resource目录下创建templates目录,然后创建test.html页面
                    Title    

            启动,测试

            四, Spring Boot与Shiro整合实现用户认证

            核心API

            • Subject: 用户主体(把操作交给SecurityManager)
            • SecurityManager:安全管理器(关联Realm)
            • Realm:Shiro连接数据的桥梁

              修改pom.xml

              • 添加shiro与spring整合依赖
                    org.apache.shiro    shiro-spring    1.10.1

                创建Realm类

                package com.example.shiro;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;/** * @Description:自定义Realm 处理登录 权限 */public class UserRleam extends AuthorizingRealm {    /**     * 执行授权逻辑     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        System.out.println("执行授权逻辑");        return null;    }    /**     * 执行认证逻辑     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        System.out.println("执行认证逻辑");        return null;    }}

                编写Shiro配置类

                package com.example.shiro;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.LinkedHashMap;import java.util.Map;/** * @Description:shiro配置类 */@Configurationpublic class ShiroConfig {    /**     * 创建ShiroFilterFactoryBean     */    @Bean    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager){        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();        //设置安全管理器        shiroFilterFactoryBean.setSecurityManager(securityManager);        //添加Shiro内置过滤器        /**         * Shiro内置过滤器,可以实现权限相关的拦截器         *    常用的过滤器:         *       anon: 无需认证(登录)可以访问         *       authc: 必须认证才可以访问         *       user: 如果使用rememberMe的功能可以直接访问         *       perms: 该资源必须得到资源权限才可以访问         *       role: 该资源必须得到角色权限才可以访问         */        Map filterMap = new LinkedHashMap();        filterMap.put("/hello", "anon");        filterMap.put("/login", "anon");        filterMap.put("/**", "authc");        //要求登陆时的链接,非必须。        shiroFilterFactoryBean.setLoginUrl("/login");        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);        return shiroFilterFactoryBean;    }    /**     * 创建DefaultWebSecurityManager     */    @Bean    public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm){        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();        //关联realm        securityManager.setRealm(userRealm);        return securityManager;    }    /**     * 创建Realm     */    @Bean    public UserRealm getRealm(){        return new UserRealm();    }}

                创建登录页面

                • 在src/main/resource目录下创建templates目录,然后创建login.html页面
                          登陆页面

                  登录

                  用户名:
                  密码:

                  编写Controller的登录逻辑

                  • 在TestController.java类中添加方法
                    /**     * 登陆页面跳转     */    @GetMapping("/login")    public String login(){        return "login";    }    /**     * 登录逻辑处理     */    @PostMapping("/login")    public String login(String username,String password,Model model){        /**         * 使用Shiro编写认证操作         */        //1.获取Subject        Subject subject = SecurityUtils.getSubject();        //2.封装用户数据        UsernamePasswordToken token = new UsernamePasswordToken(username,password);        //3.执行登录方法        try {            subject.login(token);            //登录成功            //跳转到test.html            return "redirect:/test";        } catch (UnknownAccountException e) {            //e.printStackTrace();            //登录失败:用户名不存在            System.out.println("用户名不存在");            return "login";        }catch (IncorrectCredentialsException e) {            //e.printStackTrace();            //登录失败:密码错误            System.out.println("密码错误");            return "login";        }    }

                    编写Realm的认证逻辑判断

                    package com.example.shiro;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;/** * @Description:自定义Realm 处理登录 权限 */public class UserRealm extends AuthorizingRealm {    /**     * 执行授权逻辑     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        System.out.println("执行授权逻辑");        return null;    }    /**     * 执行认证逻辑     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        System.out.println("执行认证逻辑");        //假设数据库的用户名和密码        String username = "aaa";        String password = "123";        //编写shiro判断逻辑,判断用户名和密码        //1.判断用户名        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;        if(!token.getUsername().equals(username)){            //用户名不存在            return null;//shiro底层会抛出UnKnowAccountException        }        //2.判断密码        /**         *  对比密码         * 参数1:主体对象,按需要传,登陆成功后该参数可通过SecurityUtils.getSubject().getPrincipal()获取。         * 参数2:从对象中取密码,users.getPassword()是这个用户的数据库中的密码 是用来和authenticationToken里的密码比对         * 参数3:盐,可以为空         * 参数4:当前realm的名字         */        return new SimpleAuthenticationInfo("flk好帅", password,null, getName());    }}

                    启动,测试

                    • 先访问localhost:8080/hello

                      由于在shiro过滤器中添加了filterMap.put(“/hello”, “anon”);,所以无需认证(登录)就可以访问/hello

                      • 访问localhost:8080/test

                        由于在shiro过滤器中添加了filterMap.put(“/**”, “authc”);,所以必须认证才可以访问/test,页面便跳转到登陆页面/login

                        • 输入正确的账号和密码

                          可以正常进入到test.html。

                        • 输入错误的账号或密码

                          控制台

                          账号或密码不正常,根据controller层的判断逻辑会跳转到登陆页面/login

                          五,Spring Boot整合MyBatis实现登录

                          导入mybatis相关的依赖

                                              com.alibaba            druid-spring-boot-starter            1.2.15                                            mysql            mysql-connector-java                                            org.mybatis.spring.boot            mybatis-spring-boot-starter            2.1.3        

                          配置application.yml

                          在src/main/resources目录下创建application.yml文件,并添加配置

                          spring:  datasource:    driver-class-name: com.mysql.jdbc.Driver    url: jdbc:mysql://localhost:3306/test    username: root    password: admin    type: com.alibaba.druid.pool.DruidDataSource# MyBatismybatis:  # 搜索指定包别名  type-aliases-package: com.example.domain  # 配置mapper的扫描,找到所有的mapper.xml映射文件  mapperLocations: classpath*:mapper/**/*Mapper.xml# 日志配置logging:  level:    com.example: debug

                          创建数据库,并创建表

                          • 表结构:
                          • 再插入一条数据:

                            添加User.java

                            package com.example.domain;/** * @Description:User类 */public class User {    private Integer id;    private String username;    private String password;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }}

                            添加UserMapper.java

                            package com.example.mapper;import com.example.domain.User;import org.apache.ibatis.annotations.Param;import org.springframework.stereotype.Repository;/** * @Description:Usermapper */public interface UserMapper {    User findByUsername(@Param("username") String username);}

                            添加UserMapper.xml

                            在src/main/resources/mapper目录下

                                        SELECT id,                  username,                  password        FROM            user where username = #{username}    

                            添加Service层

                            • 接口
                              package com.example.service;import com.example.domain.User;/** * @Description:IUserService */public interface IUserService {/**     * 根据用户名查询用户     * @param username 用户名     * @return     */    User findByUsername (String username);}
                              • 实现
                                package com.example.service.impl;import com.example.domain.User;import com.example.mapper.UserMapper;import com.example.service.IUserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** * @Description:UserServiceImpl */@Servicepublic class UserServiceImpl implements IUserService {    @Autowired    private UserMapper userMapper;    @Override    public User findByUsername(String username) {        return userMapper.findByUsername(username);    }}

                                在启动类Application.java中添加@MapperScan注解

                                package com.example;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * @Description: SpringBoot启动类 */@SpringBootApplication//@MapperScan指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类@MapperScan("com.example.mapper")public class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }}

                                修改UserRealm中doGetAuthenticationInfo方法的认证逻辑

                                package com.example.shiro;import com.example.domain.User;import com.example.service.IUserService;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.beans.factory.annotation.Autowired;/** * @Description:自定义Realm 处理登录 权限 */public class UserRealm extends AuthorizingRealm {    @Autowired    private IUserService userService;    /**     * 执行授权逻辑     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        System.out.println("执行授权逻辑");        return null;    }    /**     * 执行认证逻辑     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        System.out.println("执行认证逻辑");        //假设数据库的用户名和密码//        String username = "aaa";//        String password = "123";        //编写shiro判断逻辑,判断用户名和密码        //1.判断用户名        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;                //从数据库中获取用户信息        User user = userService.findByUsername(token.getUsername());        if(user == null){            //用户名不存在            return null;//shiro底层会抛出UnKnowAccountException        }        //2.判断密码        /**         *  对比密码         * 参数1:主体对象,按需要传,登陆成功后该参数可通过SecurityUtils.getSubject().getPrincipal()获取。         * 参数2:从对象中取密码,users.getPassword()是这个用户的数据库中的密码 是用来和authenticationToken里的密码比对         * 参数3:盐,可以为空         * 参数4:当前realm的名字         */        return new SimpleAuthenticationInfo("flk好帅", user.getPassword(),null, getName());    }}

                                启动,测试

                                • 输入账号密码
                                • 控制台成功打印日志

                                  六,Spring Boot与Shiro整合实现用户授权

                                  修改pom.xml

                                  • 添加aop依赖,方便开启shiro注解
                                                org.springframework.boot            spring-boot-starter-aop        

                                    修改ShiroConfig.java

                                    • 开启Shiro注解
                                      /**     * 开启Shiro注解     */    @Bean    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(            DefaultWebSecurityManager defaultWebSecurityManager) {        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);        return authorizationAttributeSourceAdvisor;    }

                                      完善UserRealm的doGetAuthorizationInfo授权逻辑

                                      /**     * 执行授权逻辑     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        System.out.println("执行授权逻辑");        //给资源进行授权        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();        //假设数据库的aaa用户的权限只有user:add        info.addStringPermission("user:add");        //info.addStringPermission("user:update");        return info;    }

                                      添加两个页面

                                      • 在src/main/resource目录下创建templates目录,然后创建add.html页面
                                                add

                                        addPage

                                        • 在src/main/resource目录下创建templates目录,然后创建update.html页面
                                                  update

                                          updatePage

                                          修改test.html页面

                                          • 添加add.html和update.html的跳转链接
                                                    Title    

                                            进入添加页面: 添加
                                            进入更新功能: 更新

                                            修改TestController.java添加页面跳转方法

                                                /**     * 添加页面跳转     */    //需要user:add权限才能访问    @RequiresPermissions("user:add")    @GetMapping("/add")    public String add(){        return "add";    }    /**     * 添加页面跳转     */    //需要user:update权限才能访问    @RequiresPermissions("user:update")    @GetMapping("/update")    public String update(){        return "update";    }

                                            启动,测试

                                            • 登陆成功后,进入add添加页面

                                              成功进入,因为它有user:add这个权限。

                                              – 控制台打印:

                                            • 登陆成功后,进入update更新页面

                                              失败进入,因为它没有user:update这个权限。

                                              – 控制台打印:

                                              (后续可以做全局异常捕获跳转到提示页面,我这边没有去弄。。。)

                                              七,thymeleaf和shiro标签整合使用

                                              修改pom.xml

                                              添加thymeleaf与shiro的扩展

                                                          com.github.theborakompanioni            thymeleaf-extras-shiro            2.0.0        

                                              修改ShiroConfig.java

                                              配置ShiroDialect,用于thymeleaf和shiro标签配合使用

                                              /**     * 配置ShiroDialect,用于thymeleaf和shiro标签配合使用     */    @Bean    public ShiroDialect getShiroDialect(){        return new ShiroDialect();    }

                                              修改test.html页面

                                                      Title    

                                              进入添加页面: 添加
                                              进入更新功能: 更新

                                              启动,测试

                                              • 登陆成功后,没有权限的标签就看不见啦~

                                                控制台打印:

上一篇:Win10再现Win7经典开始菜单风格

下一篇:贝字五笔打字轻松上手,详细教程助你掌握正确打法!