整合springboot+shiro+mybatis+thymeleaf

1.导入依赖

主要添加shiro,springboot,thymeleaf,thymeleaf-shiro的依赖

        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!--
            subject 用户
            securityManager 管理所有用户
            realm 连接用户
        -->
        <!--   shiro整合spring的包     -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.application.yml中配置数据连接和日志

  • 配置thymeleaf的缓存为false
  • 配置mybatis-plus的数据源
  • 配置mybatis-plus的日志和逻辑删除
spring:
  thymeleaf:
    cache: false
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:33060/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver

# 配置mybatisplus
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 设置日志为控制台输出
  # 配置逻辑删除
  global-config:
    db-config:
      logic-delete-value: 1 # 删除的值为1
      logic-not-delete-value: 0 # 不删除的值为0

3.编写配置类

3.1 MybatisPlusConfig类

  • 乐观锁插件
  • 分页插件
  • 逻辑删除
  • SQL执行效率插件
@Configuration  //配置类
@MapperScan("com.kuang.mapper")  //扫描mapper包
@EnableTransactionManagement  //开启事务
public class MybatisPlusConfig {

    //注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    //逻辑删除
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }

    //SQL执行效率插件
    @Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(1000);  //单位ms,设置最大执行时间,超时则不执行
        performanceInterceptor.setFormat(true);  //格式化SQL
        return performanceInterceptor;
    }
}

3.2 自定义UserRealm extends AuthorizingRealm

  • 获取到用户,根据数据库中的权限信息对用户进行授权
  • 登陆认证,判断是否有此用户

//自定义的UserRealm extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    ShiroMapper shiroMapper;  //shiro是数据库的表名,shiromapper是mapper文件,用于从数据库中查询用户

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行了授权");


        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到当前的登陆对象
        Shiro user = (Shiro)SecurityUtils.getSubject().getPrincipal();
        //设置当前用户的权限
        info.addStringPermission(user.getPerms());


        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证");
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        QueryWrapper<Shiro> wrapper = new QueryWrapper<>();
        wrapper.eq("username",userToken.getUsername());
        Shiro user = shiroMapper.selectOne(wrapper);
        System.out.println(user);
        if (null == user){
            return null;
        }

        //密码认证,shiro做
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");
    }
}

3.3 ShiroConfig类,项目页面的权限配置

这些配置方法上要添加@Bean 注解,将方法添加到spring容器中
  1. 将自定义的userRealm配置到DefaultWebSecurityManager中
  2. 将DefaultWebSecurityManager配置到ShiroFilterFactoryBean中
  3. 对页面设置访问权限
    /**
    anno: 无需认证既可以访问
    authc: 认证了才能访问
    user: 必须拥有记住我才能用
    perms: 拥有对某个资源的权限才能访问
    role: 拥有某个角色权限才能访问
    */
  4. 设置登陆的请求URL: /toLogin
  5. 设置未授权的跳转URL : /unauthorized
  6. ShiroDialect: 用来整合shiro和thymeleaf

@Configuration
public class ShiroConfig {

    //3.ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);

        //添加shiro的内置过滤器
        /**
         anno:  无需认证既可以访问
         authc:  认证了才能访问
         user:  必须拥有记住我才能用
         perms:  拥有对某个资源的权限才能访问
         role:  拥有某个角色权限才能访问
         */
        LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");
        filterMap.put("/user/*", "authc");
        bean.setFilterChainDefinitionMap(filterMap);

        //设置登陆的请求
        bean.setLoginUrl("/toLogin");
        //未授权页面
        bean.setUnauthorizedUrl("/unauthorized");
        return bean;
    }

    //2.DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //1.创建realm对象,需要自定义类
    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }

    //整合ShiroDialect: 用来整合shiro和thymeleaf
    //package at.pollux.thymeleaf.shiro.dialect;
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

}

4.controller层配置登陆的设置

  1. 用户未登陆跳转到登陆URL: /toLogin
  2. /toLogin跳转到login.html页面进行登陆,经过/login验证
  3. /login的行为如下

    创建一个token存储username,password

    使用shiro的SecurityUtils.getSubject().login() 进行登陆

    shiro会自动判断是用户名还是密码错误

    如果没错就对用户进行认证,并存储到Principal中

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

    @RequestMapping("/login")
    public String login(String username, String password, Model model) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
            return "index";
        } catch (UnknownAccountException e) {
            model.addAttribute("msg", "用户名错误");
            return "login";
        } catch (IncorrectCredentialsException e) {
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }

5.shiro整合thymeleaf,前端页面的写法

  1. 导入命名空间

    xmlns:shiro=“http://www.thymeleaf.org/thymeleaf-extras-shiro”

  2. 在div中添加 shiro:hasPermission=“user:add” 判断用户是否有add权限


    具体代码如下

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

<h1>首页</h1>
<p th:text="${msg}"></p>

<p>
    <a th:href="@{/toLogin}">登陆</a>
</p>

<div shiro:hasPermission="user:add">
    <a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update">
    <a th:href="@{/user/update}">update</a>
</div>


</body>
</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值