springboot整合shiro实现认证和授权功能(非常详细)

Shiro和Spring Security应该是我们比较常用的权限框架了,这篇文章教大家怎么通过springboot整合shiro从零开始搭建一个包含权限控制的后台管理系统。

目录

第一步:创建springboot项目

第二步:添加maven的依赖

第三步:修改配置文件

第四步:创建数据库表

第五步:创建表user对应类

第六步:创建UserRealm

第七步:创建Shiro配置类

第八步:实现登录功能

控制器层

业务层

UserRealm

持久层

第九步:测试登录功能

login.html

login.js

home.html

ShiroConfig.java

第十步:实现授权功能

UserRealm.java

UserController.java

/html/home.html 

自定义过滤器实现鉴权

ShiroConfig.java

第十一步:测试鉴权功能


第一步:创建springboot项目

通过IntelliJ IDEA创建一个springboot项目,这里的项目就命名为springboot-shiro

第二步:添加maven的依赖

修改pom.xml,添加相关的maven依赖



    4.0.0

    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.9
        
    

    cn.edu.sgu.www
    springboot-shiro
    0.0.1-SNAPSHOT
    springboot-shiro
    Spring Boot整合Shiro权限认证框架

    
        1.8
        1.3.2
        8.0.28
        1.1.21
        1.18.22
        2.0.8
        2.2.2
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.projectlombok
            lombok
            ${lombok.version}
        

        
        
            mysql
            mysql-connector-java
            ${mysql.version}
        

        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            ${mybatis.version}
        

        
        
            com.alibaba
            druid
            ${druid.version}
        

        
        
            com.alibaba
            fastjson
            ${fastjson.version}
        

        
        
            org.apache.shiro
            shiro-spring
            ${shiro.version}
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

完成前面两步之后,删除多余的test包,项目结构如图:

springboot整合shiro实现认证和授权功能(非常详细)_第1张图片

第三步:修改配置文件

修改系统的配置文件application.yml(修改默认的配置文件application.properties的名称为application.yml,只需要改后缀名),修改完成之后,把以下内容复制到application.yml中。

spring:
  profiles:
    active: dev

# mybatis的mapper.xml文件的位置
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml

最后再新建一个application-dev.yml

# 设置启动端口号
server:
  port: 8080

spring:
  # 配置数据源
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/springboot-shiro
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  # 只返回不为null的数据
  jackson:
    default-property-inclusion: non_null

第四步:创建数据库表

1、通过navicat数据库连接工具新建数据库springboot-shiro,没有用过navicat的童鞋可以参考博主的文章推荐一款非常简单实用的数据库连接工具Navicat Premiumicon-default.png?t=N7T8https://blog.csdn.net/heyl163_/article/details/132111378

springboot整合shiro实现认证和授权功能(非常详细)_第2张图片

2、在springboot-shiro数据库下创建用户表user

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '12345' COMMENT '密码',
  `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号',
  `gender` tinyint(4) UNSIGNED NOT NULL COMMENT '性别',
  `is_enable` tinyint(4) UNSIGNED NOT NULL COMMENT '启用状态',
  `last_login_time` datetime NULL DEFAULT NULL COMMENT '上一次登录时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('2023', '系统管理员', 'system', '', '18888888888', 2, 1, '2022-11-25 00:15:42');
INSERT INTO `user` VALUES ('mhxy1218', '沐雨橙风ιε', 'mumu', 'mhxy1218', '16666666666', 1, 1, '2023-07-02 00:00:29');

第五步:创建表user对应类

  • 数据库表对应实体类:User
  • 持久层接口:UserMapper
  • 业务层接口及实现类:Userservice、UserServiceImpl
  • 控制器类:UserController

springboot整合shiro实现认证和授权功能(非常详细)_第3张图片

配置mapper包扫描路径

在springboot的启动类或者任意一个配置类上使用注解@MapperScan注解配置mybatis的mapper包扫描路径

@MapperScan("cn.edu.sgu.www.shiro.mapper")

在项目根目录下创建一个config包,在config包下面创建一个MybatisConfig类。

package cn.edu.sgu.www.shiro.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

/**
 * mybatis配置类
 * @author heyunlin
 * @version 1.0
 */
@Configuration
@MapperScan("cn.edu.sgu.www.shiro.mapper")
public class MybatisConfig {

}

springboot整合shiro实现认证和授权功能(非常详细)_第4张图片

第六步:创建UserRealm

项目根目录下创建realm包,在realm包下创建UserRealm.java,并继承AuthorizingRealm,实现AuthorizingRealm的两个认证和授权的抽象方法。

package cn.edu.sgu.www.shiro.realm;

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;
import org.springframework.stereotype.Component;

/**
 * @author heyunlin
 * @version 1.0
 */
@Component
public class UserRealm extends AuthorizingRealm {
    
    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        return null;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

}

第七步:创建Shiro配置类

在config包下创建ShiroConfig.java

package cn.edu.sgu.www.shiro.config;

import cn.edu.sgu.www.shiro.realm.UserRealm;
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;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfig {

    /**
     * 配置安全管理器
     * @param userRealm UserRealm
     * @return DefaultWebSecurityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        securityManager.setRealm(userRealm);

        return securityManager;
    }

    /**
     * 配置Shiro过滤器工厂
     * @param securityManager 安全管理器
     * @return ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 注册安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        /*
         * 设置登录页面的地址
         * 当用户访问认证资源的时候,如果用户没有登录,那么就会跳转到该属性指定的页面
         */
        shiroFilterFactoryBean.setLoginUrl("/login.html");

        return shiroFilterFactoryBean;
    }

}

第八步:实现登录功能

控制器层

在UserController类中添加一个login()方法,新建UserLoginDTO对象来接收前端传来的用户名和密码,同时通过validation验证这两个字段。

package cn.edu.sgu.www.shiro.controller;

import cn.edu.sgu.www.shiro.dto.UserLoginDTO;
import cn.edu.sgu.www.shiro.restful.JsonResult;
import cn.edu.sgu.www.shiro.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author heyunlin
 * @version 1.0
 */
@RestController
@RequestMapping(path = "/user", produces = "application/json;charset=utf-8")
public class UserController {

    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping(path = "/login", method = RequestMethod.POST)
    public JsonResult login(UserLoginDTO loginDTO) {
        userService.login(loginDTO);

        return JsonResult.success();
    }

}

业务层

package cn.edu.sgu.www.shiro.service;

import cn.edu.sgu.www.shiro.dto.UserLoginDTO;

/**
 * @author heyunlin
 * @version 1.0
 */
public interface UserService {

    /**
     * 登录认证
     * @param loginDTO 登录信息
     */
    void login(UserLoginDTO loginDTO);
}

UserServiceImpl中实现用户登录的业务代码,当我们调用Subject的login()方法时,会执行UserRealm下面的认证方法doGetAuthenticationInfo()

package cn.edu.sgu.www.shiro.service.impl;

import cn.edu.sgu.www.shiro.dto.UserLoginDTO;
import cn.edu.sgu.www.shiro.entity.User;
import cn.edu.sgu.www.shiro.exception.GlobalException;
import cn.edu.sgu.www.shiro.mapper.UserMapper;
import cn.edu.sgu.www.shiro.restful.ResponseCode;
import cn.edu.sgu.www.shiro.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author heyunlin
 * @version 1.0
 */
@Service
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    @Autowired
    public UserServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public void login(UserLoginDTO loginDTO) {
        String username = loginDTO.getUsername();

        // 根据用户名查询用户信息
        User user = userMapper.selectByUsername(username);

        if (user != null) {
            if (user.getIsEnable()) {
                // shiro登录认证
                UsernamePasswordToken token = new UsernamePasswordToken(username, loginDTO.getPassword());
                Subject subject = SecurityUtils.getSubject();

                subject.login(token);
                // 设置session失效时间:永不超时
                subject.getSession().setTimeout(-1001);
            } else {
                throw new GlobalException(ResponseCode.FORBIDDEN, "账号已被锁定,禁止登录!");
            }
        } else {
            throw new GlobalException(ResponseCode.NOT_FOUND, "用户名不存在~");
        }
    }

}

UserRealm

实现认证的方法,当调用Subject.login()方法时,在shiro框架内部会去调用realm的认证方法。

package cn.edu.sgu.www.shiro.realm;

import cn.edu.sgu.www.shiro.entity.User;
import cn.edu.sgu.www.shiro.exception.GlobalException;
import cn.edu.sgu.www.shiro.mapper.UserMapper;
import cn.edu.sgu.www.shiro.restful.ResponseCode;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
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;
import org.springframework.stereotype.Component;

/**
 * @author heyunlin
 * @version 1.0
 */
@Component
public class UserRealm extends AuthorizingRealm {

    private final UserMapper userMapper;

    @Autowired
    public UserRealm(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

        // 得到用户名
        String username = token.getUsername();
        // 根据用户名查询用户信息
        User user = userMapper.selectByUsername(username);

        if (user == null) {
            throw new GlobalException(ResponseCode.BAD_REQUEST, "登录失败,用户不存在~");
        }
        if (user.getIsEnable()) {
            String password = new String(token.getPassword());

            if (user.getPassword().equals(password)) {
                return new SimpleAuthenticationInfo(user, password, username);
            } else {
                throw new GlobalException(ResponseCode.BAD_REQUEST, "用户名或密码错误,登录失败!");
            }
        }

        return null;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

}

持久层

UserMapper接口新增selectByUsername()方法

package cn.edu.sgu.www.shiro.mapper;

import cn.edu.sgu.www.shiro.entity.User;
import org.springframework.stereotype.Repository;

/**
 * @author heyunlin
 * @version 1.0
 */
@Repository
public interface UserMapper {

    /**
     * 根据用户名查询用户信息
     * @param username 用户名
     * @return User 查询到的用户信息
     */
    User selectByUsername(String username);
}

通过xml的方式绑定sql语句






    
        
        
        
        
        
        
        
    

    

第九步:测试登录功能

创建几个简单的页面试一下效果

准备工作:

在resources目录下创建static目录,存放静态资源文件,在static目录下创建js和html目录,把jquery.min.js复制到js目录下。

login.html

static目录下创建登录页面login.html



    
        
        登录页面
    

    
        
用户名
密码

login.js

js目录下创建login.js,点击登录按钮时提交用户的数据到接口/user/login,完成登录操作

$(document).ready(function () {

    $("#login").click(function () {
        let username = $("#username").val();
        let password = $("#password").val();

        $.post("/user/login", {
            username: username,
            password: password
        }, function (res) {
           if (res.code === 200) {
               location.href = "/html/home.html";
           }
        });
    });

});

home.html

html目录下创建一个页面home.html



    
        
        系统首页
    

    
        

欢迎来到系统首页!

ShiroConfig.java

添加资源访问规则,配置登录页面和登录接口的地址可以不需要登录认证就能访问,同时/html/home.html需要登录才能访问。

package cn.edu.sgu.www.shiro.config;

import cn.edu.sgu.www.shiro.realm.UserRealm;
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;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfig {

    /**
     * 配置安全管理器
     * @param userRealm UserRealm
     * @return DefaultWebSecurityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        securityManager.setRealm(userRealm);

        return securityManager;
    }

    /**
     * 配置Shiro过滤器工厂
     * @param securityManager 安全管理器
     * @return ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 注册安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        /*
         * 设置登录页面的地址
         * 当用户访问认证资源的时候,如果用户没有登录,那么就会跳转到指定的页面
         */
        shiroFilterFactoryBean.setLoginUrl("/login.html");

        // 定义资源访问规则
        Map map = new LinkedHashMap<>();

        /*
         * 过滤器说明
         * anon:不需要认证就可以访问的资源
         * authc:需要登录认证才能访问的资源
         */
        map.put("/html/home.html", "authc");

        // 不需要认证就能访问
        map.put("/login.html", "anon");
        map.put("/user/login", "anon");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }

}

当我们访问localhost:8080/login.html时,输入mumu/mhxy1218,点击登录时,会跳转到/html/home.html。

然后我们清空浏览器缓存,刷新页面,发现页面重定向回了login.html。这是因为在shiro配置类里配置了/html/home.html要身份认证之后才能访问。

map.put("/html/home.html", "authc");

第十步:实现授权功能

接下来,讲解如何通过shiro完成授权,在UserRealm里的doGetAuthorizationInfo()方法中实现授权的代码,查询用户的权限保存到shiro中,为了方便演示效果,我们模拟几条数据。

UserRealm.java

完成doGetAuthorizationInfo()方法的具体实现

package cn.edu.sgu.www.shiro.realm;

import cn.edu.sgu.www.shiro.entity.User;
import cn.edu.sgu.www.shiro.exception.GlobalException;
import cn.edu.sgu.www.shiro.mapper.UserMapper;
import cn.edu.sgu.www.shiro.restful.ResponseCode;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * @author heyunlin
 * @version 1.0
 */
@Component
public class UserRealm extends AuthorizingRealm {

    private final UserMapper userMapper;

    @Autowired
    public UserRealm(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

        // 得到用户名
        String username = token.getUsername();
        // 根据用户名查询用户信息
        User user = userMapper.selectByUsername(username);

        if (user == null) {
            throw new GlobalException(ResponseCode.BAD_REQUEST, "登录失败,用户不存在~");
        }
        if (user.getIsEnable()) {
            String password = new String(token.getPassword());

            if (user.getPassword().equals(password)) {
                return new SimpleAuthenticationInfo(user, password, username);
            } else {
                throw new GlobalException(ResponseCode.BAD_REQUEST, "用户名或密码错误,登录失败!");
            }
        }

        return null;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        Set permissions = new HashSet<>();

        permissions.add("/user/delete");
        permissions.add("/user/update");

        authorizationInfo.setStringPermissions(permissions);

        return authorizationInfo;
    }

}

UserController.java

在UserController中添加两个方法delete()和update()

package cn.edu.sgu.www.shiro.controller;

import cn.edu.sgu.www.shiro.dto.UserLoginDTO;
import cn.edu.sgu.www.shiro.restful.JsonResult;
import cn.edu.sgu.www.shiro.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author heyunlin
 * @version 1.0
 */
@RestController
@RequestMapping(path = "/user", produces = "application/json;charset=utf-8")
public class UserController {

    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping(path = "/login", method = RequestMethod.POST)
    public JsonResult login(UserLoginDTO loginDTO) {
        userService.login(loginDTO);

        return JsonResult.success();
    }

    @RequestMapping(path = "/delete", method = RequestMethod.POST)
    public JsonResult delete() {
        return JsonResult.success("删除成功");
    }

    @RequestMapping(path = "/update", method = RequestMethod.POST)
    public JsonResult update() {
        return JsonResult.success("修改成功");
    }

}

/html/home.html 

home.html中新增两个按钮,同时还有引入jquery。



    
        
        系统首页
        
    

    
        

欢迎来到系统首页!

|

自定义过滤器实现鉴权

自定义过滤器AuthorizationFilter实现鉴权功能,注意,这个过滤器只处理接口资源,所以把项目的静态资源/路径作为排除项,静态资源直接放行。

package cn.edu.sgu.www.shiro.filter;

import cn.edu.sgu.www.shiro.restful.JsonResult;
import cn.edu.sgu.www.shiro.restful.ResponseCode;
import com.alibaba.fastjson.JSON;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 鉴权过滤器
 * @author heyunlin
 * @version 1.0
 */
@WebFilter
public class AuthorizationFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        String requestURI = request.getRequestURI();
        Subject subject = SecurityUtils.getSubject();

        if (subject != null && !subject.isPermitted(requestURI)) {
            HttpServletResponse response = (HttpServletResponse) resp;
            response.setContentType("application/json;charset=utf-8");

            // 构建返回对象
            JsonResult jsonResult= JsonResult.error(ResponseCode.UNAUTHORIZED, "正在访问未授权的资源");
            String data = JSON.toJSONString(jsonResult);

            response.getWriter().write(data);
            return;
        }

        chain.doFilter(req, resp);
    }

}

ShiroConfig.java

把自定义过滤器加入到shiro的过滤器链中,处理删除和修改两个接口。

map.put("/user/delete", "authorization");
map.put("/user/update", "authorization");

package cn.edu.sgu.www.shiro.config;

import cn.edu.sgu.www.shiro.filter.AuthorizationFilter;
import cn.edu.sgu.www.shiro.realm.UserRealm;
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 javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfig {

    /**
     * 配置安全管理器
     * @param userRealm UserRealm
     * @return DefaultWebSecurityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        securityManager.setRealm(userRealm);

        return securityManager;
    }

    /**
     * 配置Shiro过滤器工厂
     * @param securityManager 安全管理器
     * @return ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 注册安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        /*
         * 设置登录页面的地址
         * 当用户访问认证资源的时候,如果用户没有登录,那么就会跳转到指定的页面
         */
        shiroFilterFactoryBean.setLoginUrl("/login.html");

        // 定义资源访问规则
        Map map = new LinkedHashMap<>();

        /*
         * 过滤器说明
         * anon:不需要认证就可以访问的资源
         * authc:需要登录认证才能访问的资源
         */
        map.put("/html/home.html", "authc");

        // 不需要认证就能访问
        map.put("/login.html", "anon");
        map.put("/user/login", "anon");

        // 设置自定义过滤器
        map.put("/user/delete", "authorization");
        map.put("/user/update", "authorization");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        Map filters = shiroFilterFactoryBean.getFilters();
        filters.put("authorization", new AuthorizationFilter());
        shiroFilterFactoryBean.setFilters(filters);

        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }

}

第十一步:测试鉴权功能

为了测试,注释掉修改接口的资源权限,然后重启一下项目。

springboot整合shiro实现认证和授权功能(非常详细)_第5张图片

点击删除按钮会提升删除成功,但是修改的时候提示未授权。

springboot整合shiro实现认证和授权功能(非常详细)_第6张图片

好了,文章就分享到这里了,如果看完这篇文章感觉对你有所帮助,不要忘了点赞+收藏哦~

代码已经上传到git仓库,可按需获取:

springboot整合shiro实现认证和授权功能icon-default.png?t=N7T8https://gitee.com/he-yunlin/springboot-shiro.git

更多代码详情,请参考博主的另一篇文章:

springboot整合shiro实现认证和授权功能改进icon-default.png?t=N7T8https://blog.csdn.net/heyl163_/article/details/131518274

你可能感兴趣的:(spring,boot,java,后端)