springboot整合shiro的实战教程(二)

文章目录

  • 整合思路
    • 1.创建springboot项目
    • 2.引入依赖
    • 3.创建Shiro Filter
      • 0.创建配置类
      • 1.配置shiroFilterFactoryBean
      • 2.配置WebSecurityManager
      • 3.创建自定义Relm
      • 4.配置自定义realm
      • 5.编写控制器跳转至index.html
      • 6.加入资源的权限控制
      • 7. 常见过滤器
  • 登录认证实现
    • 登录界面
    • 开发controller
    • 开发realm中返回静态数据(未连接数据库)
  • 退出认证实现
    • 页面按钮
    • 开发Controller
  • MD5、Salt的认证实现
    • 开发数据库注册
      • 1.用户注册页面
      • 2.创建用户注册表
      • 3.引入依赖
      • 4.配置数据源
      • 5.创建实体类
      • 6.开发controller
      • 7.开发Service
      • 8.创建DAO接口
      • 9.创建salt工具类
    • 开发数据库注册认证
      • 1.开发DAO
      • 2.开发Service层
      • 3.开发在工厂中获取bean对象的工具类
      • 4.修改自定义realm
      • 5.修改ShiroConfig中realm使用凭证匹配器以及hash散列

整合思路

在这里插入图片描述

1.创建springboot项目

在这里插入图片描述

2.引入依赖

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring-boot-starter</artifactId>
  <version>1.5.3</version>
</dependency>

3.创建Shiro Filter

0.创建配置类

在这里插入图片描述

1.配置shiroFilterFactoryBean

@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
  //创建shiro的filter
  ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  //注入安全管理器
  shiroFilterFactoryBean.setSecurityManager(securityManager);
 	
  return shiroFilterFactoryBean;
}

2.配置WebSecurityManager

@Bean
public DefaultWebSecurityManager getSecurityManager(Realm realm){
  DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
  defaultWebSecurityManager.setRealm(realm);
  return defaultWebSecurityManager;
}

3.创建自定义Relm

public class CustomerRealm extends AuthorizingRealm {
    //处理授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
		//处理认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws 
      																																		AuthenticationException {
        return null;
    }
}

4.配置自定义realm

//创建自定义realm
@Bean
public Realm getRealm(){
  return new CustomerRealm();
}

5.编写控制器跳转至index.html

@Controller
public class IndexController {
    @RequestMapping("index")
    public String index(){
        System.out.println("跳转至主页");
        return "index";
    }
}

6.加入资源的权限控制

修改ShiroFilterFactoryBean配置

//注入安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> map =  new LinkedHashMap<>();
map.put("/**","authc");
//配置认证和授权规则
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

/** 代表拦截项目中一切资源 authc 代表shiro中的一个filter的别名,详细内容看文档的shirofilter列表

7. 常见过滤器

  • 注意: shiro提供和多个默认的过滤器,我们可以用这些过滤器来配置控制指定url的权限:
配置缩写对应的过滤器功能
anonAnonymousFilter指定url可以匿名访问
authcFormAuthenticationFilter指定url需要form表单登录,默认会从请求中获取usernamepassword,rememberMe等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑,但是一般都是我们自己在控制器写登录逻辑的,自己写的话出错返回的信息都可以定制嘛。
authcBasicBasicHttpAuthenticationFilter指定url需要basic登录
logoutLogoutFilter登出过滤器,配置指定url就可以实现退出功能,非常方便
noSessionCreationNoSessionCreationFilter禁止创建会话
permsPermissionsAuthorizationFilter需要指定权限才能访问
portPortFilter需要指定端口才能访问
restHttpMethodPermissionFilter将http请求方法转化成相应的动词来构造一个权限字符串,这个感觉意义不大,有兴趣自己看源码的注释
rolesRolesAuthorizationFilter需要指定角色才能访问
sslSslFilter需要https请求才能访问
userUserFilter需要已登录或“记住我”的用户才能访问

登录认证实现

登录界面

<form action="${pageContext.request.contextPath}/user/login" method="post">
  用户名:<input type="text" name="username" > <br/>
  密码  : <input type="text" name="password"> <br>
  <input type="submit" value="登录">
</form>

开发controller

@Controller
@RequestMapping("user")
public class UserController {
  /**
    * 用来处理身份认证
    * @param username
    * @param password
    * @return
    */
  @RequestMapping("login")
  public String login(String username,String password){
    //获取主体对象
    Subject subject = SecurityUtils.getSubject();
    try {
      subject.login(new UsernamePasswordToken(username,password));
      return  "redirect:/index.jsp";
    } catch (UnknownAccountException e) {
      e.printStackTrace();
      System.out.println("用户名错误!");
    }catch (IncorrectCredentialsException e){
      e.printStackTrace();
      System.out.println("密码错误!");
    }
    return "redirect:/login.jsp";
  }
}

开发realm中返回静态数据(未连接数据库)

@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("==========================");
        String principal = (String) token.getPrincipal();
        if("xiaochen".equals(principal)){
            return new SimpleAuthenticationInfo(principal,"123",this.getName());
        }
        return null;
    }
}

退出认证实现

页面按钮

 <a href="${pageContext.request.contextPath}/user/logout">退出用户</a>

开发Controller

@Controller
@RequestMapping("user")
public class UserController {
  /**
    * 退出登录
    *
    */
  @RequestMapping("logout")
  public String logout(){
    Subject subject = SecurityUtils.getSubject();
    subject.logout();//退出用户
    return "redirect:/login.jsp";
  }
}

MD5、Salt的认证实现

开发数据库注册

1.用户注册页面

<h1>用户注册</h1>
<form action="${pageContext.request.contextPath}/user/register" method="post">
  用户名:<input type="text" name="username" > <br/>
  密码  : <input type="text" name="password"> <br>
  <input type="submit" value="立即注册">
</form>

2.创建用户注册表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `username` varchar(40) DEFAULT NULL,
  `password` varchar(40) DEFAULT NULL,
  `salt` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

3.引入依赖

<!--mybatis相关依赖-->
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.1.2</version>
</dependency>

<!--mysql-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.38</version>
</dependency>


<!--druid-->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.19</version>
</dependency>

4.配置数据源

server.port=8888
server.servlet.context-path=/shiro
spring.application.name=shiro

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
#新增配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shiro?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root


mybatis.type-aliases-package=com.baizhi.springboot_jsp_shiro.entity
mybatis.mapper-locations=classpath:com/baizhi/mapper/*.xml

5.创建实体类

@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private String  id;
    private String username;
    private String password;
    private String salt;

    //定义角色集合
    private List<Role> roles;


}

6.开发controller

@Controller
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 用户注册
     */
    @RequestMapping("register")
    public String register(User user) {
        try {
            userService.register(user);
            return "redirect:/login.jsp";
        }catch (Exception e){
            e.printStackTrace();
            return "redirect:/register.jsp";
        }
    }
}

7.开发Service

public interface UserService {
    //注册用户方法
    void register(User user);
}
@Override
    public void register(User user) {
        //处理业务调用dao
        //1.生成随机盐
        String salt = SaltUtils.getSalt(8);
        //2.将随机盐保存到数据
        user.setSalt(salt);
        //3.明文密码进行md5 + salt + hash散列
        Md5Hash md5Hash = new Md5Hash(user.getPassword(),salt,1024);
        user.setPassword(md5Hash.toHex());
        userDAO.save(user);
    }

8.创建DAO接口

@Mapper
public interface UserDAO {
    void save(User user);
}
<insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
  insert into t_user values(#{id},#{username},#{password},#{salt})
</insert>

9.创建salt工具类

public class SaltUtils {
    /**
     * 生成salt的静态方法
     * @param n
     * @return
     */
    public static String getSalt(int n){
        char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            char aChar = chars[new Random().nextInt(chars.length)];
            sb.append(aChar);
        }
        return sb.toString();
    }
}

开发数据库注册认证

我们需要根据用户名查询来判定用户注册的操作是否合法

1.开发DAO

@Mapper
public interface UserDAO {

    void save(User user);
		//根据身份信息认证的方法
    User findByUserName(String username);
}
<select id="findByUserName" parameterType="String" resultType="User">
  select id,username,password,salt from t_user
  where username = #{username}
</select>

2.开发Service层

public interface UserService {
    //注册用户方法
    void register(User user);
    //根据用户名查询业务的方法
    User findByUserName(String username);
}
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDAO userDAO;
    @Override
    public User findByUserName(String username) {
        return userDAO.findByUserName(username);
    }
}

3.开发在工厂中获取bean对象的工具类

解决给自定义的Realm注入业务对象。

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }


    //根据bean名字获取工厂中指定bean 对象
    public static Object getBean(String beanName){
        return context.getBean(beanName);
    }
}

4.修改自定义realm

 @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("==========================");

        //根据身份信息
        String principal = (String) token.getPrincipal();
        //在工厂中获取service对象
        UserService userService = (UserService) ApplicationContextUtils.getBean("userService");
				//根据身份信息查询
        User user = userService.findByUserName(principal);

        if(!ObjectUtils.isEmpty(user)){
            //返回数据库信息
            return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), 
                                               ByteSource.Util.bytes(user.getSalt()),this.getName());
        }
        return null;
    }

5.修改ShiroConfig中realm使用凭证匹配器以及hash散列

@Bean
public Realm getRealm(){
  CustomerRealm customerRealm = new CustomerRealm();
  //设置hashed凭证匹配器
  HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
  //设置md5加密
  credentialsMatcher.setHashAlgorithmName("md5");
  //设置散列次数
  credentialsMatcher.setHashIterations(1024);
  customerRealm.setCredentialsMatcher(credentialsMatcher);
  return customerRealm;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/445342.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能在信息系统安全中的运用

一、 概述 对于企业和消费者来讲&#xff0c;人工智能是非常有用的工具&#xff0c;那又该如何使用人工智能技术来保护敏感信息?通过快速处理数据并预测分析&#xff0c;AI可以完成从自动化系统到保护信息的所有工作。尽管有些黑客利用技术手段来达到自己的目的&#xff0c;但…

恋活2 仿原神人物卡系列2全合集打包

内含&#xff1a;炽沙话事人 芭别尔迪希雅镀金女团 -沙中净水镀金女团 -叶轮舞者珐露珊坎蒂丝柯莱可莉丽莎-叶隐芳名神里绫华-花时来信瑶瑶。 下载地址&#xff1a; https://www.changyouzuhao.cn/13661.html

浅谈2024 年 AI 辅助研发趋势!

目录 ​编辑 引言 一、AI辅助研发现状 1. 技术发展 2. 工具集成 3. 应用场景 二、AI辅助研发趋势 1. 更高的自动化程度 2. 更高的智能化程度 3. 更多的领域应用 4. 更高的重视度 三、结论 四. 完结散花 悟已往之不谏&#xff0c;知来者犹可追 创作不易&#xff…

STM32用标准库做定时器定时1秒更新OLED的计数值(Proteus仿真)

首先新建proteus工程&#xff0c;绘制电路图&#xff1a; 然后赋值我之前文章中提到的文件夹OLED屏幕显示&#xff1a;&#xff08;没有的自己去那篇文章下载去&#xff09; 然后进入文件夹&#xff1a; 新建两个文件在Mycode文件夹中&#xff1a; 文件关系如下&#xff1a; 新…

leetcode2

翻转链表 struct ListNode* reverseList(struct ListNode* head) {struct ListNode* prev NULL;struct ListNode* curr head;while (curr ! NULL) {struct ListNode* nextTemp curr->next;//nextTemp的作用是为了记录&#xff0c;以便再反转后可以curr->next prev; …

SpringBoot基础入门

SpringBoot2讲义链接 源码链接 springboot中文网 由于讲义中有代码的详细实现步骤&#xff0c;故此笔记只记录理论部分&#xff0c;项目具体构建细节需搭配 讲义 食用 csdn比较好的博客 第一章 JavaConfig 项目见讲义第1章&#xff0c;项目名为 001-springboot-pre Xml 配置容…

HTML_CSS_盒子模型

盒子模型组成 内容区域&#xff08;comtent&#xff09;内边距区域&#xff08;padding&#xff09;边框区域&#xff08;border&#xff09;外边距区域&#xff08;margin&#xff09; 布局标签 标签&#xff1a;<div> </div> 和 <span> …

2024年,如何使用chatgpt4.0为工作赋能?

ChatGPT 4.0的工作原理和功能 ChatGPT 4.0的工作原理和功能可以从以下几个方面进行详细说明&#xff1a; 工作原理 ChatGPT 4.0的工作原理主要基于深度学习技术&#xff0c;特别是Transformer模型的应用。它通过大量的文本数据进行训练&#xff0c;学习语言的模式和规律&…

MySQL 的基础操作

数据库的基础操作 1. 库操作2. 表的操作3. 数据类型 数据库是现代应用程序中至关重要的组成部分&#xff0c;通过数据库管理系统&#xff08;DBMS&#xff09;存储和管理数据。 1. 库操作 创建数据库 创建数据库是开始使用数据库的第一步。下面是一些常见的创建数据库的示例&a…

嘉绩咨询创新招商落地方案,助力品牌加速市场渗透

领先的渠道招商全案系统孵化平台——嘉绩咨询&#xff0c;今日发布了其创新的招商落地方案&#xff0c;此举标志着企业在加速品牌拓展和市场渗透方面迈出了坚实的步伐。嘉绩咨询专注于为企业提供包容性和深度一体化的服务&#xff0c;从招商教育、招商落地到项目孵化等多方位助…

【leetcode热题】 二叉树的后序遍历

给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[3,2,1]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#xff1a;root [1] 输出…

微信小程序uniapp+django+python的酒店民宿预订系统ea9i3

Android的民宿预订系统设计的目的是为用户提供民宿客房、公告信息等方面的平台。 与PC端应用程序相比&#xff0c;Android的民宿预订系统的设计主要面向于民宿&#xff0c;旨在为管理员和用户、商家提供一个Android的民宿预订系统。用户可以通过Android及时查看民宿客房等。 An…

FreeRTOS操作系统学习——同步互斥与通信

同步&#xff08;Synchronization&#xff09; 同步是一种机制&#xff0c;用于确保多个任务能够按照特定的顺序协调执行或共享数据。当一个任务需要等待其他任务完成某个操作或满足某个条件时&#xff0c;同步机制可以帮助任务进行协调和等待。 在FreeRTOS中&#xff0c;常见…

力扣--动态规划5.最长回文子串

class Solution { public:string longestPalindrome(string s) {// 获取输入字符串的长度int n s.size();// 如果字符串长度为1&#xff0c;直接返回原字符串&#xff0c;因为任何单个字符都是回文串if (n 1)return s;// 创建一个二维数组dp&#xff0c;用于记录子串是否为回…

【Python】成功解决ModuleNotFoundError: No module named ‘seaborn’

【Python】成功解决ModuleNotFoundError: No module named ‘seaborn’ &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; …

掌握项目进度管理:确保项目按时交付的关键策略

项目进度管理是确保项目按时、按预算完成的重要环节。在项目执行过程中&#xff0c;项目进度可能会受到各种因素的影响&#xff0c;如资源不足、任务延误、需求变更等。因此&#xff0c;掌握项目进度管理的关键策略对于项目经理来说至关重要。本文将介绍一些实用的项目进度管理…

011-keep-alive详解

keep-alive详解 1、简介2、keep-alive的使用效果未使用keep-alive的效果图使用keep-alive的效果图include和exclude指定是否缓存某些组件使用keep-alive的钩子函数执行顺序问题 3、keep-alive的应用场景举例4、总结 1、简介 keep-alive 是 Vue 的内置组件&#xff0c;当它包裹…

什么是自动化测试?什么情况下使用?

什么是自动化测试? 自动化测试是指把以人为驱动的测试行为转化为机器执行的过程。实际上自动化测试往往通过一些测试工具或框架&#xff0c;编写自动化测试脚本&#xff0c;来模拟手工测试过程。比如说&#xff0c;在项目迭代过程中&#xff0c;持续的回归测试是一项非常枯燥…

解决阿里云服务器开启frp服务端,内网服务器开启frp客户端却连接不上的问题

解决方法&#xff1a; 把阿里云自带的Alibabxxxxxxxlinux系统 换成centos 7系统&#xff01;&#xff01;&#xff01;&#xff01; 说一下我的过程和问题&#xff1a;由于我们内网的服务器在校外是不能连接的&#xff0c;因此我弄了个阿里云服务器做内网穿透&#xff0c;所谓…

【C++】二叉树进阶之二叉搜索树

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握二叉搜索树&#xff0c;能自己模拟实现二…