Springboot整合Shiro之认证

举报
波波烤鸭 发表于 2022/03/31 02:27:09 2022/03/31
【摘要】   Shiro是我们常用的一个权限管理框架,我们之前已经详细的给大家介绍过了Shiro的基础知识,不太清楚的可以参考下 https://blog.csdn.net/qq_38526573/category...

  Shiro是我们常用的一个权限管理框架,我们之前已经详细的给大家介绍过了Shiro的基础知识,不太清楚的可以参考下 https://blog.csdn.net/qq_38526573/category_9284714.html 此文,本文的重点是来介绍下在SpringBoot环境下我们怎么来使用Shiro。

一、添加相关依赖

本案例中我们使用SpringDataJPAThymeleaf来配合讲解,所以相关的依赖如下

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.3.2</version>
    </dependency>
    <!-- springBoot的启动器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- mysql -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>

    <!-- druid连接池 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.0.9</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

二、添加相关的配置信息

  在application.properties中添加如下的配置信息

# jdbc 的相关信息
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/srm?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456

# 配置连接池信息
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

# 配置jpa的相关参数
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

三、业务准备

  我们提前将登录认证的后台业务先完成。我们提前将登录认证的后台业务先完成。

1.对应的表结构

CREATE TABLE `t_user` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `salt` varchar(100) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `state` int(1) DEFAULT NULL,
  `last_login_time` datetime DEFAULT NULL,
  `nickname` varchar(30) DEFAULT NULL,
  `realname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

2.pojo对象

package com.dpb.springboot41shiro.pojo;

import javax.persistence.*;

/**
 * @program: springboot-41-shiro
 * @description:
 * @author: 波波烤鸭
 * @create: 2019-11-29 20:06
 */
@Entity
@Table(name = "t_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @Column(name = "username")
    private String username;
    @Column(name = "password")
    private String password;
    @Column(name = "salt")
    private String salt;
    @Column(name = "realname")
    private String realname;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getRealname() {
        return realname;
    }

    public void setRealname(String realname) {
        this.realname = realname;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

3.dao接口

  接口我们通过 JpaRepository接口来实现,然后根据名称规则来定义方法

public interface UserDao extends JpaRepository<User,Integer> {

    /**
     * 根据账号查询
     * @param username
     * @return
     */
    List<User> findByUsername(String username);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4.业务层代码

  业务层就实现简单的调用即可
在这里插入图片描述

四、Shiro整合

  接下来我们就可以来整合Shiro框架了

1.自定义Realm文件

  首先我们定义一个realm实现类来实现我们认证和授权的逻辑

package com.dpb.springboot41shiro.realm;

import com.dpb.springboot41shiro.pojo.User;
import com.dpb.springboot41shiro.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.apache.shiro.util.SimpleByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * @program: springboot-41-shiro
 * @description: 自定义Realm
 * @author: 波波烤鸭
 * @create: 2019-11-29 19:37
 */
public class AuthcRealm extends AuthorizingRealm {

    /**
     * 认证的方法
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
                return null;
    }

    /**
     * 授权的方法
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

逻辑可以稍后实现

2.Shiro的配置类

  我们先来看下之前在spring整合shiro的时候,我们的整合配置文件:
在这里插入图片描述
那么我们在SpringBoot中只需将此配置转换为对应的java配置即可,如下

package com.dpb.springboot41shiro.config;

import com.dpb.springboot41shiro.realm.AuthcRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: springboot-41-shiro
 * @description: Shiro的配置类
 * @author: 波波烤鸭
 * @create: 2019-11-29 19:31
 */
@Configuration
public class ShiroConfig {

    @Value("${shiro.hashAlgorithmName}")
    private String hashAlgorithmName;

    @Value("${shiro.hashIterations}")
    private Integer hashIterations;

    /**
     * 获取凭证匹配器
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName(hashAlgorithmName);
        matcher.setHashIterations(hashIterations);
        return matcher;
    }

    /**
     * 获取自定义的Realm
     * @return
     */
    @Bean
    public AuthcRealm authcRealm(){
        AuthcRealm realm = new AuthcRealm();
        realm.setCredentialsMatcher(hashedCredentialsMatcher());
        return realm;
    }

    /**
     * 获取SecurityManager对象
     * @return
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authcRealm());
        return manager;
    }

    /**
     * 注册ShiroFilterFactoryBean
     * @return
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager manager){
        ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
        filter.setSecurityManager(manager);
        filter.setLoginUrl("/login.do");
        filter.setSuccessUrl("/success.html");
        filter.setUnauthorizedUrl("/refuse.html");
        // 设置过滤器
        Map<String,String> map = new HashMap<>();
        map.put("/css/**","anon");
        map.put("/img/**","anon");
        map.put("/js/**","anon");
        map.put("/login","anon");
        map.put("/login.do","authc");
        map.put("/**","authc");
        filter.setFilterChainDefinitionMap(map);
        return filter;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

3.访问测试

  到此shiro已经被集成到了我们项目中,我们可以根据我们配置的过滤链路来启动访问下,首先创建如下的相关文件,便于测试
在这里插入图片描述
同时添加对应的跳转控制器

/**
 * @program: springboot-41-shiro
 * @description: 基础控制器
 * @author: 波波烤鸭
 * @create: 2019-11-29 19:52
 */
@Controller
public class BaseController {

    @RequestMapping("/{path}")
    public String page(@PathVariable  String path){
        return path;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

访问需要认证的success.html ,会给错误提示
访问img/a2.jpg可以直接访问

在这里插入图片描述

五、登录认证测试

  接下来我们实现下认证的过程。

1.自定义realm实现登录

  自定义realm认证的流程如下

@Autowired
private UserService service;

/**
 * 认证的方法
 * @param authenticationToken
 * @return
 * @throws AuthenticationException
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    String userName = token.getUsername();
    System.out.println("开始登录认证:"+userName);
    List<User> list = service.login(userName);
    if (list == null || list.size() != 1) {
        return null;
    }
    User user = list.get(0);

    return new SimpleAuthenticationInfo(user,user.getPassword(),new SimpleByteSource(user.getSalt()),"authcRealme");
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2.创建登录表单

  前端我们用Thymeleaf来作为模块框架,创建登录表单

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>登录管理</h1>
    <form th:action="@{/login.do}" method="post">
        账号:<input type="text" name="username"><br>
        密码:<input type="text" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3.创建认证的控制器

  同时我们创建认证的控制器,来处理认证失败的情况

package com.dpb.springboot41shiro.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

/**
 * @program: springboot-41-shiro
 * @description: 认证的控制器
 * @author: 波波烤鸭
 * @create: 2019-11-29 20:12
 */
@Controller
public class AuthcController {

    @RequestMapping("/login.do")
    public String login(HttpServletRequest request){
        Object obj = request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
        System.out.println("认证的错误信息:" + obj);
        return "/login";
    }

    /**
     * 注销的方法
     * @return
     */
    @RequestMapping("/logout.do")
    public String logout(){
        SecurityUtils.getSubject().logout();
        return "redirect:/login";
    }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

4.准备数据

  我们可以自己通过Md5加密一个密码然后保存到数据库中
在这里插入图片描述

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

5.测试

到此启动项目,登录测试即可

在这里插入图片描述

最后项目的目录结构如下:
在这里插入图片描述

文章来源: dpb-bobokaoya-sm.blog.csdn.net,作者:波波烤鸭,版权归原作者所有,如需转载,请联系作者。

原文链接:dpb-bobokaoya-sm.blog.csdn.net/article/details/103322744

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200