SpringBoot和shiro整合项目实战二(图解超详细)

承接上一篇博客:https://blog.csdn.net/qq_41115379/article/details/112978080
这是下一篇博客:https://blog.csdn.net/qq_41115379/article/details/113088489
首先要说的是,这个项目实战是参考自黑马,可以去对应视频看一看:https://www.bilibili.com/video/BV1ct411x7CN
接下来按照这几个步骤
在这里插入图片描述

首先要了解,shiro有着几个核心api

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

然后是在pox里导入shiro的依赖

<!-- 导入shiro和spring整合依赖 -->

    <dependency>

      <groupId>org.apache.shiro</groupId>

      <artifactId>shiro-spring</artifactId>

      <version>1.4.0</version>

    </dependency>

并且自定义一个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;

/**
 * 自定义的Realm shiro有两个功能,认证和授权,所以刚好实现这两个功能
 */
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("执行认证逻辑");
        return null;
    }
}

然后是创建shiro类

package com.example.shiro;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {
    /**
     * 创建Realm bean会让方法返回的对象放入到spring的环境,以便使用
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }
    /**
     * 创建DefaultWebSecurityManager
     */
    //这里的传参有点特殊可以调用一个注解,这里有个细节,想看看注解区不区分大小写
    //实测,会报错。。。所以是区分大小写的
    // @Qualifier 注释指定注入 Bean 的名称,是用来消除歧义的
    //这里也要有Bean
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        //关联realm,并且这个是需要传参的
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
        //感觉和直接return一个 new的一样吧 之所以不直接return是因为,会调用一个
        //关联realm的方法
    }
    /**
     * 创建shiroFilterFactoryBean
     */
    //也是需要注解和参数的
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //设置一个安全管理器来关联SecurityManager
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        return shiroFilterFactoryBean;
    }

}

位置如下
在这里插入图片描述
使用shiro内置过滤器实现页面拦截
先在templates下创建用户添加add.html和用户更新的界面update.html
add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户添加页面</title>
</head>
<body>
用户添加
</body>
</html>

update.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户更新页面</title>
</head>
<body>
用户更新
</body>
</html>

并且修改test.html 让他能跳转到这两个其他的界面
test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试用的</title>
</head>
<body>
<hs th:text="${name}"></hs>
<hr/>
进入用户添加功能:<a href="user/add.html">用户添加</a><br/>
进入用户更新功能:<a href="user/update.html">用户更新</a><br/>
</body>
</html>

结构如下:
在这里插入图片描述
然后就可以启动application
浏览器输入
http://localhost:8080/testThymeleaf
在这里插入图片描述
但是会发现,点击用户添加或者用户更新,都会出现
在这里插入图片描述
解决方法的话,主要是在于这个项目是用spring写的,所以都是用的自动装配,所以直接在controller那边新加入这两个就可以了

UserController新添加的类

  //用户的增加
    @RequestMapping("/add")
    public String add(){
        System.out.println("UserController.add()");
        //这里返回的是路径
        //所以是需要删除ResponseBody
        return "user/add";
    }
    //用户的更新
    @RequestMapping("/update")
    public String update(){
        System.out.println("UserController.update()");
        //同理返回路径
        return "user/update";
    }

并把test再修改一下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试用的</title>
</head>
<body>
<hs th:text="${name}"></hs>
<hr/>
进入用户添加功能:<a href="add">用户添加</a><br/>
进入用户更新功能:<a href="update">用户更新</a><br/>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

再开始正式添加shiro内置过滤器,先介绍一下,他有五种:

anon:无序认证(登录)就可以访问
authc:必须认证才可以访问
user:如果使用rememberMe的功能可以直接访问
perms:该资源必须得到资源权限才可以访问
role:该资源必须得到角色权限才可以访问

然后往shiroConfig里添加数据

package com.example.shiro;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    /**
     * 创建Realm bean会让方法返回的对象放入到spring的环境,以便使用
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }
    /**
     * 创建DefaultWebSecurityManager
     */
    //这里的传参有点特殊可以调用一个注解,这里有个细节,想看看注解区不区分大小写
    //实测,会报错。。。所以是区分大小写的
    // @Qualifier 注释指定注入 Bean 的名称,是用来消除歧义的
    //这里也要有Bean
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        //关联realm,并且这个是需要传参的
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
        //感觉和直接return一个 new的一样吧 之所以不直接return是因为,会调用一个
        //关联realm的方法
    }
    /**
     * 创建shiroFilterFactoryBean
     */
    //也是需要注解和参数的
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //设置一个安全管理器来关联SecurityManager
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //添加shiro内置过滤器
        //先创建一个Map集合
        Map<String,String> filterMap=new LinkedHashMap<String,String>();
        //然后往里面添加东西
        filterMap.put("/add","authc");
        filterMap.put("/update","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

}

然后启动这个application
会发现这个错误:
在这里插入图片描述
拦截成功会默认到这个jsp文件 所以需要进行修改,到我们让他跳转的页面
所以有一个新写的login方法
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
登录页面
</body>
</html>

然后对应的改写UserController和在shiro里面增加对应的功能
UserController

package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {
    //测试方法
    @ResponseBody
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("UserController.hello()");
        return "ok";
    }
    //在使用 @RequestMapping后,返回值通常解析为跳转路径,
    // 但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body
    //测试thymeleaf
    //所以注意的是 这边是没加@ResponseBody,也就是他就是一个跳转路径,所以要创建一个test
    @RequestMapping("/testThymeleaf")
    public String testThymeleaf(Model model){
        //把数据存入到model中
        model.addAttribute("name","wzw");
        //返回界面
        return "test";
    }
    //用户的增加
    @RequestMapping("/add")
    public String add(){
        System.out.println("UserController.add()");
        //这里返回的是路径
        //所以是需要删除ResponseBody
        return "user/add";
    }
    //用户的更新
    @RequestMapping("/update")
    public String update(){
        System.out.println("UserController.update()");
        //同理返回路径
        return "user/update";
    }
    //用户的的登录
    @RequestMapping("/login")
    public String login(){
        System.out.println("UserController.login()");
        //同理返回路径
        return "login";
    }



}

shrioConfig

package com.example.shiro;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    /**
     * 创建Realm bean会让方法返回的对象放入到spring的环境,以便使用
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }
    /**
     * 创建DefaultWebSecurityManager
     */
    //这里的传参有点特殊可以调用一个注解,这里有个细节,想看看注解区不区分大小写
    //实测,会报错。。。所以是区分大小写的
    // @Qualifier 注释指定注入 Bean 的名称,是用来消除歧义的
    //这里也要有Bean
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        //关联realm,并且这个是需要传参的
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
        //感觉和直接return一个 new的一样吧 之所以不直接return是因为,会调用一个
        //关联realm的方法
    }
    /**
     * 创建shiroFilterFactoryBean
     */
    //也是需要注解和参数的
    //这里也是需要bean注解的
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //设置一个安全管理器来关联SecurityManager
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //添加shiro内置过滤器
        //先创建一个Map集合
        Map<String,String> filterMap=new LinkedHashMap<String,String>();
        //然后往里面添加东西
        filterMap.put("/add","authc");
        filterMap.put("/update","authc");

        /**
         * 修改调整的登录页面
         */
        //然后这个跳转的页面,就是需要control来进行自动装入这个页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

}

这样就可以了
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值