springboot+mybatis整合shiro

本文介绍了如何在SpringBoot项目中集成Apache Shiro框架,包括配置ShiroConfig、自定义UserRealm进行用户认证和权限管理,以及如何在Controller层实现登录拦截和认证功能。通过一个简单的Demo演示了如何处理登录错误和实现基本的权限控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考了b站的springboot视频。
1、shiro简介
它是阿帕奇的java安全框架。包含了三个主要对象:subject(当前用户)、SecurityManager(安全管理)、Realm(数据相关)。
在这里插入图片描述
Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。其基本功能点如下图所示:
在这里插入图片描述
shiro详细介绍
2、demo结构:
在这里插入图片描述
3、使用了springboot、mybatis、druid etc,实现登录控制,用户认证、请求授权(本文没有实现授权)等。
4、首先搭建环境:
java配置类Shiroconfig和自定义的Realm对象:UserRealm。它们之间的联系建立再Realm这个对象上。
Shiroconfig:(可以配置登录拦截和授权)

package com.example.shiro_pht.config;

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 {
    //shiro的三大对象:suject securityManager realm

    //shiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getsfb(@Qualifier("getdsm") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //1、实现登录拦截
        //添加shiro的内置过滤器
        /*
        anon:无需认证就能访问
        authc:必须认证
        user:必须拥有remember me功能才能
        perms:拥有某个资源的权限才能使用
        role:拥有角色权限才能访问

        必须用到setFilterChainDefinitionMap,设置过滤器链,打开其源码,其参数为一个map,用于添加
         */
        Map<String, String> filterChainDefinitionMap=new LinkedHashMap<>();

        //权限操作(顺序要注意)
        //filterChainDefinitionMap.put("/userpage/add","perms[userpage:add]"); //只有带了user:add的用户才有权限访问
        //filterChainDefinitionMap.put("/userpage/update","perms[userpage:update]");

        //登录认证拦截
        filterChainDefinitionMap.put("/userpage/add","anon"); //这个路径无需认证
        filterChainDefinitionMap.put("/userpage/*","authc"); //即这个路径必须认证,否则跳转到错误页面
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        //如果没有权限则跳转到一个页面(这里我们跳转到登录页面)
        shiroFilterFactoryBean.setLoginUrl("/tologin");
        //跳转到未授权页面
        //shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");

        return shiroFilterFactoryBean;
    }

    //DefaultWebSecurityManager
    @Bean
    public DefaultWebSecurityManager getdsm(@Qualifier("realms") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        //关联realm
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
    }

    //realm对象,使用自定义的realm类对象
    @Bean
    public UserRealm realms(){
        return new UserRealm();
    }
}

自定义Realm对象,UserRealm(认证部分连接了service层,获取数据库中的用户名和密码),其中的token,它与Hellocontroller中的token是互通的(在框架环境下),直接调用:

package com.example.shiro_pht.config;

import com.example.shiro_pht.Pojo.User;
import com.example.shiro_pht.service.Userservice;
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;

//自定义realm,继承AuthorizingRealm即可
public class UserRealm extends AuthorizingRealm {

    @Autowired
    Userservice userservice;
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权操作!");
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了认证操作!");
        //upt即token,它与Hellocontroller中的token是互通的,直接调用!!!
        //这里很重要!!!
        UsernamePasswordToken upt=(UsernamePasswordToken)authenticationToken;
        //连接数据库

        User user=userservice.queryuser(upt.getUsername());

        System.out.println(upt);
        System.out.println(upt.getUsername());
        if(user==null){
            return null; //抛出错误
        }
        return new SimpleAuthenticationInfo("",user.getPassword(),"");
    }
}

5、Controller层:

package com.example.shiro_pht.Controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;

import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class Hellocontroller {
    @RequestMapping({"/", "/index"})
    public String hello(Model model) {
        model.addAttribute("msg", "hello");
        return "index";
    }

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

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

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

    @RequestMapping("/login")
    public String login(@RequestParam("name") String name,@RequestParam("password") String password, Model model) {
        System.out.println(name);
        System.out.println(password);

        //使用shiro获取当前用户
        Subject userNow = SecurityUtils.getSubject();
        //获取令牌
        UsernamePasswordToken token = new UsernamePasswordToken(name, password);

        try {
            //执行登录的方法,这步封装很复杂
            userNow.login(token);
            return "index";
        } catch (UnknownAccountException e) {
            model.addAttribute("msg", "用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }

    /*
    @RequestMapping("/noauth")
    @ResponseBody
    public String unauth(){
        return "没有权限";
    }
    */
}

6、mapper层,Usermapper:

package com.example.shiro_pht.mapper;

import com.example.shiro_pht.Pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface Usermapper {
    public User queryuser(String name);
}

7、实体类:

package com.example.shiro_pht.Pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private String password;
}

8、由于功能简单,service层接口与mapper层方法相同,实现类Userserviceimp:

package com.example.shiro_pht.service;

import com.example.shiro_pht.Pojo.User;
import com.example.shiro_pht.mapper.Usermapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class Userserviceimp implements Userservice{
    @Autowired
    Usermapper usermapper;
    @Override
    public User queryuser(String name) {
        User user=usermapper.queryuser(name);
        return user;
    }
}

9、resources:
mapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.shiro_pht.mapper.Usermapper">
    <select id="queryuser" resultType="user">
        select * from accountlist where name=#{name}
    </select>
</mapper>

index.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p th:text="${msg}"></p>
This is the first page!
<a href="/userpage/add">add</a><br>
<a href="/userpage/update">update</a>
</body>
</html>

login.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<h1>登录页面</h1>
<p th:text="${msg}" style="color:#f60202"></p>
<form th:action="@{/login}">
    username:<input type="text" name="name"><br>
    password:<input type="text" name="password"><br>
    <input type="submit" value="submit">
    <input type="reset" value="reset">
</form>
</body>
</html>

application.yaml:

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/majinbuu1?serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 500

    filters: stat,wall,log4j
    maxPoolPreparedAtatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: durid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.shiro_pht.Pojo

add.html与update.html略。就一句body。
10、实验报错与结果:
报错:
1、org.apache.shiro.authc.UsernamePasswordToken - null报错:
通过打印输出测试,最终发现错误为前端传值的名字和后端接收时不匹配。(username----->name)
2、授权页面无法跳转,按照网上的说法,调整了Shiroconfig中授权和拦截的顺序,仍然不行,貌似授权页面无法跳转,因为是懒加载blabla,未解决…

结果:
数据库中的所有账户密码都能登录,且正确的实现了拦截、认证等。
这只是个入门级别的demo,记录下学习过程,以后有机会再深入学习。

### 解决 PP-OCRv4 出现的错误 当遇到 `WARNING: The pretrained params backbone.blocks2.0.dw_conv.lab.scale not in model` 这样的警告时,这通常意味着预训练模型中的某些参数未能匹配到当前配置下的模型结构中[^2]。 对于此问题的一个有效解决方案是采用特定配置文件来适配预训练权重。具体操作方法如下: 通过指定配置文件 `ch_PP-OCRv4_det_student.yml` 并利用已有的最佳精度预训练模型 (`best_accuracy`) 来启动训练过程可以绕过上述不兼容的问题。执行命令如下所示: ```bash python3 tools/train.py -c configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_student.yml ``` 该方案不仅解决了参数缺失带来的警告,还能够继续基于高质量的预训练成果进行微调,从而提升最终检测效果。 关于蒸馏的概念,在机器学习领域内指的是将大型复杂网络(teacher 模型)的知识迁移到小型简单网络(student 模型)。这里 student 和 teacher 的关系是指两个不同规模或架构的神经网络之间的指导与被指导的关系;其中 teacher 已经经过充分训练并具有良好的性能,而 student 则试图模仿前者的行为模式以达到相似的效果但保持更高效的计算特性。 至于提到的 `Traceback` 错误信息部分,由于未提供具体的跟踪堆栈详情,难以给出针对性建议。不过一般而言,这报错往往涉及代码逻辑错误或是环境配置不当等问题。为了更好地帮助定位和解决问题,推荐记录完整的异常日志,并仔细检查最近修改过的代码片段以及确认依赖库版本的一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值