shiro与springboot整合

2023-05-16

##  Shiro 与 SpringBoot 的整合

1.创建SpringBoot工程,导入依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
</dependency>

2.配置application.properties**

# 数据库配置
# 默认使用mysql的驱动是8.x的版本,注意driver-class-name,url中增加时区的配置
#spring.datasource.url=jdbc:mysql://localhost:3306/java1907?serverTimezone=Asia/Shanghai
#spring.datasource.username=root
#spring.datasource.password=root
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/java1907?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver


# mybatis配置
# 配置别名需要扫描的包
#mybatis.type-aliases-package=com.qf.entity
# 引入映射文件
#mybatis.mapper-locations=classpath:mapper/*.xml

spring.thymeleaf.cache=false
spring.thymeleaf.encoding=utf-8
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.servlet.content-type=text/html

3.编写ShiroRealm

package com.qf.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;

public class ShiroRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        return null;
    }
}

4.编写ShiroConfig:

package com.qf.config;

import com.qf.realm.ShiroRealm;
import org.apache.shiro.mgt.SecurityManager;
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;

@Configuration
public class ShiroConfig {

    //配置shiro过滤器
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //创建Shiro工厂对象
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证,跳转到指定资源(比如登陆页面)
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        //没有权限操作时跳转的资源路径
        shiroFilterFactoryBean.setUnauthorizedUrl("/refuse");
        //认证成功统一跳转到/index
        //shiroFilterFactoryBean.setSuccessUrl("/index");

        //创建LinkedHashMap对象,需要保证添加顺序(很关键)
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // authc:必须认证通过才可以访问;
        // anon: 匿名访问
        //过滤链定义,从上向下顺序执行,一般将/**放在最下边
        //一般静态资源可以设置匿名访问(不拦截)
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        //设置登录URL不拦截
        filterChainDefinitionMap.put("/login", "anon");

        // 退出时,指定logout过滤器
        //filterChainDefinitionMap.put("/logout", "logout");

        //必须放在所有权限设置的最后,所有url都必须认证通过才可以访问
        filterChainDefinitionMap.put("/**", "authc");

        //指定url都必须认证通过才可以访问
        //filterChainDefinitionMap.put("/list", "authc");

        //所有url都不需要认证通过就可以访问(匿名访问)
        //filterChainDefinitionMap.put("/**", "anon");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    // 安全管理对象
    @Bean
    public SecurityManager createSecurityManager() {

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(createShiroRealm());

        return securityManager;
    }

    // 自定义realm对象
    public ShiroRealm createShiroRealm() {

        ShiroRealm shiroRealm = new ShiroRealm();

        return shiroRealm;
    }
}
过滤器简称对应的java类
anonorg.apache.shiro.web.filter.authc.AnonymousFilter
authcorg.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasicorg.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
permsorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
portorg.apache.shiro.web.filter.authz.PortFilter
restorg.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
rolesorg.apache.shiro.web.filter.authz.RolesAuthorizationFilter
sslorg.apache.shiro.web.filter.authz.SslFilter
userorg.apache.shiro.web.filter.authc.UserFilter
logoutorg.apache.shiro.web.filter.authc.LogoutFilter

authc:/admins/user/**=authc表示需要认证(登录)才能使用,FormAuthenticationFilter是表单认证,没有参数

roles:/admins/user/=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/=roles[“admin,guest”],每个参数通过才算通过,相当于hasAllRoles()方法。

perms:/admins/user/=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/=perms[“user:add:,user:modify:”],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。

rest:/admins/user/=rest[user],根据请求的方法,相当于/admins/user/=perms[user:method] ,其中method为post,get,delete等。

port:/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。

authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证

ssl:/admins/user/**=ssl没有参数,表示安全的url请求,协议为https

user:/admins/user/**=user没有参数表示必须存在用户, 身份认证通过或通过记住我认证通过的可以访问,当登入操作时不做检查

anon,authcBasic,auchc,user是认证过滤器

perms,roles,ssl,rest,port是授权过滤器

5.UserController

package com.qf.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

    @RequestMapping("/list")
    public String list(){
        return "list";
    }

@RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("/login")
    public String login(){
        return "login";
}

@RequestMapping("/refuse")
public String refuse(){
    return "refuse";
    }

@RequestMapping("/index")
public String index(){
        return "index";
    }
}

6.编写对应的login.html页面(以及list,refuse,index页面)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>登录页面</h1>

    <form action="login" method="post">
        用户名:<input type="text" name="username" /><br /><br />
        密码:<input type="password" name="password" /><br /><br />
        <input type="submit" value="登录" /><br />

    </form>


    <font color="red" th:text="${msg}"></font>

</body>
</html>

#### 实现用户认证

1.修改UserController中的login方法

@RequestMapping("/login")
public String login(String username, String password, Model model) {

    //存储输入的用户名密码
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    //主体对象
    Subject subject = SecurityUtils.getSubject();

    try {
        //登陆判断
        subject.login(token);
        //认证成功跳转到主页
        return "index";
    } catch (UnknownAccountException e) {
        model.addAttribute("msg", "账号不存在");
        return "login";
    } catch (IncorrectCredentialsException e) {
        model.addAttribute("msg", "密码错误");
        return "login";
    }
}

2.修改ShiroRealm中的AuthenticationInfo方法

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

    //用户名
    String principal = (String)authenticationToken.getPrincipal();
    System.out.println(principal);

    //密码
    Object credentials = authenticationToken.getCredentials();
    String password = new String((char[]) credentials);
    System.out.println(password);

    if("jack".equals(principal) && "123".equals(password)){

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,password,"");

        return simpleAuthenticationInfo;
    }
    return null;
}

#### 实现用户授权

1.在ShiroConfig中的shiroFilter方法中添加被授权的信息

//配置授权过滤器,设置未授权访问URL
filterChainDefinitionMap.put("/list","perms[user:list]");

配置之后重启项目,该资源路径则无法访问,此时需要配置授权信息

2.修改ShiroRealm中的doGetAuthorizationInfo方法

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

    simpleAuthorizationInfo.addStringPermission("user:list");

    return simpleAuthorizationInfo;

}

####Shiro整合thymleaf标签

1.导入依赖

<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>

2.在ShiroConfig中添加该方法

@Bean
public ShiroDialect getShiroDialect(){
    return new ShiroDialect();
}

3.修改index.html页面中测试

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>主页</h1>

    <a href="用户查询" shiro:hasPermission="user:list">用户查询</a>
    <a href="用户修改" shiro:hasPermission="user:update">用户修改</a>

    <a href="用户删除" >用户删除</a>
</body>
</html>

####实现用户退出

1.在相关html页面中添加超链接

<a href="logout">退出</a>

2.在ShiroConfig中的shiroFilter方法中添加退出配置

//配置退出
map.put("/logout","logout");

3.在UserController中添加logout方法

@RequestMapping("/logout")
public String logout(){

    Subject subject = SecurityUtils.getSubject();

    subject.logout();

    return "toLogin";
}

rememberMe

1.在login.html页面中添加记住我

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <h1>登录</h1>

    <form action="login" method="post">
        用户名:<input type="text" name="username"> <br><br>
        密码:<input type="password" name="password"> <br><br>

        <input type="checkbox" name="rememberMe">记住我 <br><br>
        <input type="submit" value="登录">
    </form>
    <font color="#ff3044" th:text="${msg}"></font>
</body>
</html>

2.在UserController中的login方法配置rememberMe参数

@RequestMapping("/login")
public String login(String username, String password, Model model,boolean rememberMe){

    System.out.println("rememberMe类型:"+rememberMe);

    //获取令牌
    UsernamePasswordToken token = new UsernamePasswordToken(username,password,rememberMe);
    //获取主体

    Subject subject = SecurityUtils.getSubject();

    try{

        //判断认证是否通过

        subject.login(token);
        //跳转页面

        return "list";


    }catch (Exception e){

        //保存提示信息

        model.addAttribute("msg","用户名或密码错误");

        //跳转页面
        return "login";

    }

}

3.在ShiroConfig类中编写相关代码

package com.qf.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.qf.realm.ShiroRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;


@Configuration
public class ShiroConfig {

    @Bean

    public CookieRememberMeManager getCookieRememberMeManager(){

        //创建Cookie
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");

        simpleCookie.setMaxAge(3600*24*365);



        //创建管理Cookie对象
        CookieRememberMeManager cookieRememberMeManager = new 
CookieRememberMeManager();
        cookieRememberMeManager.setCookie(simpleCookie);


        return cookieRememberMeManager;

    }

    @Bean
    public ShiroDialect getShiroDialect(){

        return new ShiroDialect();
    }

    //配置realm
    @Bean

    public ShiroRealm createShiroRealm() {
        ShiroRealm shiroRealm = new ShiroRealm();

        return shiroRealm;

    }

    //配置realm
    @Bean
    public SecurityManager createSecurityManager() {

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        securityManager.setRealm(createShiroRealm());

        securityManager.setRememberMeManager(getCookieRememberMeManager());

        return securityManager;

    }

    //配置shiro过滤器

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean (SecurityManager 
securityManager) {

        //配置shiroFilter工厂对象

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);


        //未认证跳转URL

        shiroFilterFactoryBean.setLoginUrl("/toLogin");

        //认证成功之后跳转URL(一般不设置)
        //shiroFilterFactoryBean.setSuccessUrl("/index");

        //未授权跳转URL
        shiroFilterFactoryBean.setUnauthorizedUrl("/refuse");

        //创建有序的Map集合
        LinkedHashMap<String, String> map = new LinkedHashMap<>();

        //配置过滤资源
        //放行资源,不拦截
        map.put("/js/**","anon");
        map.put("/css/**","anon");
        map.put("/login","anon");

        //配置rememberMe访问路径
        map.put("/list","user");

        //设置访问权限
        map.put("/add","perms[user:add]");

        //配置退出
        map.put("/logout","logout");

        //访问某个资源进行认证

        //map.put("/list","authc");

        //所有资源都必须认证通过后才能访问
        map.put("/**","authc");

        //所有资源都可以匿名访问
        //map.put("/**","anon");

        //设置过滤信息
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

shiro与springboot整合 的相关文章

随机推荐

  • 第二十五课.元学习MetaLearning

    目录 元学习介绍相似度对比的应用 xff1a Few shot Learning问题概述孪生网络SiameseNetworkLearning Pairwise Similarity ScoresTriplet Loss 预训练与微调 参数初
  • C++循环依赖的一些解决方法

    若存在两个类A B使得A类中含有B类的对象且B类中包含A类的对象 xff0c 则称A B之间存在循环依赖 如 class B class A public B b class B public A a 若两个类之间存在循环依赖则在编译时会报
  • Read-only file system怎么解决?

    Read only file system怎么解决 xff1f 我的思路是先查看 proc mounts文件里面的目录的权限 xff0c 确定是否缺少w权限 如果确定缺少的话 xff1a 解决方法 xff1a mount o remount
  • php 上传文件 出现413 Request Entity Too Large问题的解决方法

    配置 xff1a php 43 nginx 需求 xff1a 上传小文件正常 xff0c 上传大于2M 的PDF文件就提示 出现413 Request Entity Too Large问题的解决方法 经过排查 xff0c 这是nginx 拦
  • C语言中,通过指针得到相应数组的长度

    通过指针得到相应数组的长度 xff0c 1 通过指针得到浮点型数组的长度 2 通过指针得到字符串型数组的长度 得到浮点型数组长度 int arrayVlenth float p int len 61 0 while p p 43 43 le
  • Python监控目录文件夹,并使用SFTP上传目录及文件到linux服务器

    Python 扫描监控本地文件夹并进行超大文件上传 方案1 WebUploader大文件分块多线程并发上传 方案2 watchdog目录文件夹监控 paramiko STFP上传服务器 方案3 优化2 压缩后上传 服务器解压 1 监控本地文
  • 本地组策略编辑器关闭windows10的自动更新

    具体操作 xff1a win 43 R输入 gpedit msc 打开组策略 xff0c 在 计算机配置 管理模板 windows组件 Windows更新 里找到 指定Intranet microsoft 更新服务位置 xff0c 双击打开
  • PVE虚拟机篇-PVE虚拟机安装

    安装包下载 前往Proxmox Virtual Environment下载ISO镜像文件 xff0c 可以直接选择最新版本 但是如果没有海外线路一般下载十分缓慢 xff0c 甚至下不动 xff0c 所以可以去中科大镜像源 xff1a 中科大
  • PVE虚拟机篇-pve软件换源

    起因 由于安装pve的第二天突然发现后台显示执行错误 xff0c 更新软件源失败 xff1a 更新软件源方法 注释企业源 echo 34 deb https enterprise proxmox com debian pve bullsey
  • 解决android opengl glReadPixels 慢的问题 二

    解决android opengl glReadPixels 慢的问题 二 上篇讲到使用pbo解决glreadpix慢的问题 xff0c 但是效果不太理想 xff0c 后来参考链接 xff1a OpenGL Pixel Buffer Obje
  • Tesseract 3.02中文字库训练

    下载chi sim traindata字库 下载tesseract ocr setup 3 02 02 exe 下载地址 xff1a http code google com p tesseract ocr downloads list 下
  • Windows下使用pip安装包 出错 TLS/SSL

    Windows下使用pip安装包的时候出现如下问题 xff1a WARNING pip is configured with locations that require TLS SSL however the ssl module in
  • C++进阶(七)-模板与群体数据8

    选择排序 选择排序的基本思想 每次从待排序序列中选择一个关键字最小的元素 xff0c xff08 当需要按关键字升序排列时 xff09 xff0c 顺序排在已排序序列的最后 xff0c 直至全部排完 例9 12 简单选择排序函数模板 tem
  • Ubuntu 20.04 WARNING笔记(长期更新,欢迎交流)

    记录使用Ubuntu 20 04过程的报错 以及解决 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • 循环嵌套例题

    循环嵌套例题 1 例题1 span class token comment 代码 span span class token keyword for span span class token punctuation span span c
  • java实现学生信息管理(对象数组实现)

    java实现学生信息管理 xff08 对象数组实现 xff09 1 例题 实体类 学生类 id 姓名 xff0c 年龄 xff0c 性别 xff0c 成绩 需要使用数组保存学生信息 Student allStu 需要完成的方法 1 根据学生
  • java基础语法思维导图

    java从入门到放弃 简单总结之前的
  • 学生管理系统2.0 (可对学生数组扩容)

    学生管理系统2 0 可对学生数组扩容 1 用户可初始化数组长度 xff0c 不够用时可以扩充数组容量 尝试完成以下功能 实体类 学生类 id 姓名 xff0c 年龄 xff0c 性别 xff0c 成绩 需要使用数组保存学生信息 Studen
  • LinkedList和Set

    LinkedList和Set 1 LinkedList 1 1 LinkedList概述 底层存储数据是一个双向链表结构 自行车链子 就是一个生活中链表结构 xff0c 环环相扣 xff0c 替换 xff0c 拆除非常方便 1 2 Link
  • shiro与springboot整合

    Shiro 与 SpringBoot 的整合 1 创建SpringBoot工程 xff0c 导入依赖 span class token generics function span class token punctuation lt sp