spring boot整合Shiro实现单点登录的示例代码

下面是关于“spring boot整合Shiro实现单点登录的示例代码”的详细攻略。

环境准备

首先,我们需要准备以下环境:

  • JDK 8
  • Maven
  • IDE:Eclipse 或者 Intellij IDEA

在环境准备完成后,我们接下来需要进行以下的准备工作。

创建Spring Boot工程

我们可以通过Maven快速构建一个Spring Boot应用程序,然后加上Shiro依赖即可。

  1. 打开Eclipse或者Intellij IDEA,创建一个普通的Maven工程;
  2. 在pom.xml文件中添加以下的Spring Boot依赖:
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.4.0</version>
</dependency>
  1. 执行命令 mvn clean install 完成依赖的下载

Shiro基本配置

接下来,我们需要进行Shiro的基本配置

  1. 创建ShiroConfig类

在src/main/java下创建一个ShiroConfig类

@Configuration
public class ShiroConfig {
    /**
     * 配置Shiro到Spring容器
     * @param securityManager
     * @return
     */
    @Bean(name = "shiroFilter")
    protected ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //声明securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //注册authcFilter过滤器
        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("authc", authcFilter());
        shiroFilterFactoryBean.setFilters(filters);

        //为URL设置访问所需要的角色
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/login", "authc");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        shiroFilterFactoryBean.setLoginUrl("/login");

        return shiroFilterFactoryBean;
    }

    /**
     * 创建securityManager
     *
     * @return
     */
    @Bean(name = "securityManager")
    protected DefaultWebSecurityManager defaultWebSecurityManager(UserRealm bean) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //注入Realm
        securityManager.setRealm(bean);
        return securityManager;
    }

    /**
     * 创建Realm
     *
     * @return
     */
    @Bean(name = "realm")
    public UserRealm userRealm() {
        return new UserRealm();
    }

    /**
     * 注册authcFilter过滤器
     * @return
     */
    @Bean(name = "authc")
    public AuthenticationFilter authcFilter() {
        UsernamePasswordAuthenticationFilter authcFilter = new UsernamePasswordAuthenticationFilter();
        authcFilter.setLoginUrl("/login");
        return authcFilter;
    }
}
  1. 创建一个UserRealm类

在src/main/java下创建一个UserRealm类:

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        User user = (User) principalCollection.getPrimaryPrincipal();

        //获取角色ResouceCode关联信息
        List<ResouceCode> resouceCodeList = userService.selectResourceCodeList(user.getUserName());
        //将role和url加入到授权对象中
        if (resouceCodeList != null && resouceCodeList.size() > 0) {
            for (ResouceCode resouceCode : resouceCodeList) {
                authorizationInfo.addRole(resouceCode.getRoleCode().toUpperCase());
                authorizationInfo.addStringPermission(resouceCode.getResCode().toLowerCase());
            }
        }

        return authorizationInfo;
    }

    /**
     * 验证 登录
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String username = usernamePasswordToken.getUsername();
        if (StringUtils.isBlank(username)) {
            return null;
        }

        User user = userService.selectUserByUserName(username);
        if (user == null) {
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getCredentialsSalt()), getName());

        return authenticationInfo;
    }
}

编写Controller和View

接下来,我们需要编写Controller和View

  1. 添加登录页面

在src/main/resources下创建login.html页面:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登陆</title>
</head>
<body>
<div>
<form method="post" th:action="@{/login}">
<div>
<label>用户名: <input type="text" name="username" required></label>
</div>
<div>
<label>密码: <input type="password" name="password" required></label>
</div>
<div><input type="submit" value="登陆"></div>
</form>
</div>
</body>
</html>
  1. 创建HomeController类

在src/main/java下创建一个HomeController类,实现登录成功后的跳转:

@Controller
public class HomeController {

    /**
     * 登录成功后跳转到主页面
     *
     * @return
     */
    @RequestMapping("/home")
    public String home() {
        return "/views/home";
    }
}
  1. 创建IndexController类

在src/main/java下创建一个IndexController类,实现登录和退出:

@Controller
public class IndexController {

    /**
     * 登录
     *
     * @return
     */
    @RequestMapping("/login")
    public String login() {
        return "/views/login";
    }

    /**
     * 退出
     *
     * @return
     */
    @RequestMapping("/logout")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "redirect:/login";
    }
}
  1. 创建Home页面

在src/main/resources/views下创建一个home.html页面,实现登录验证后的统一页面:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>首页</title>
</head>
<body>
<h1>欢迎访问首页</h1>
</body>
</html>

两个示例说明

下面我们演示两个Shiro单点登录的应用:

示例一:普通登录

  1. 在浏览器中输入网址 http://localhost:8080/login,会跳转到登录页面;
  2. 在登录页面中输入用户名和密码,点击“登陆”,会跳转到应用的首页:http://localhost:8080/home,同时在请求头中设置了Cookie;
  3. 访问 http://localhost:8080/home,会发现并没有被拦截,说明登录成功;

示例二:多个应用的单点登录

假设有两个应用APP1和APP2,在浏览器中访问APP1,然后跳转到APP2,由于已经实现了Shiro单点登录,所以在访问APP2时,就无需再次输入用户名和密码。

  1. 访问APP1,执行登录操作,成功登录;
  2. 在APP1的页面上添加访问APP2页面的链接,并设置URL为APP2的登录页面URL;
  3. 点击APP2的链接,跳转到APP2的登录页面,此时我们并不需要再次输入用户名和密码;
  4. 点击APP2的首页链接,会发现并没有被拦截,说明登录成功。

总结

至此,我们已经完成了Spring Boot整合Shiro实现单点登录的示例代码。需要注意的是,这里的示例是最基本的示例,如果想要在实际应用中使用,还需要根据实际情况进行具体的配置和开发。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring boot整合Shiro实现单点登录的示例代码 - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • Java由浅入深全面讲解方法的使用

    Java由浅入深全面讲解方法的使用 什么是方法? 方法是一组可以被重复使用的代码块。它可以接受参数并返回结果。在Java中,方法是类的基本组成部分,通过方法可以完成对类的成员变量进行操作,并实现不同功能的代码块重用。 如何定义方法? 在Java中,方法由方法名和一对括号()组成,括号中可以定义传递给方法的参数列表。方法的代码块用{}包围。定义方法的基本语法如…

    Java 2023年5月26日
    00
  • Java多线程模拟电影售票过程

    关于Java多线程模拟电影售票过程的攻略,可以分为以下几个步骤: 确定需求 在开始实现之前,需要首先明确需求。在本例中,我们需要模拟一个电影院售票过程。具体而言,要求程序能够模拟多个售票窗口同时对外售票,每个售票窗口需要从已有的电影票中售出一张票。当电影票售罄时,所有售票窗口需要停止售票。最后,统计每个售票窗口售出的票数以及总票数。 实现思路 在明确需求之后…

    Java 2023年5月26日
    00
  • JAVA多线程之中断机制及处理中断的方法

    JAVA多线程之中断机制及处理中断的方法 在多线程编程中,线程可能会因为各种原因(比如等待不必要的资源、等待IO操作或者Long Running操作)而进入阻塞状态,我们常使用中断机制来解决这种情况。 中断机制 简单来说,中断机制就是用来打断阻塞状态的线程。当一个线程被中断时,它会收到一个 InterruptedException 异常,执行中断处理方法;如…

    Java 2023年5月18日
    00
  • 详解Java中的反射机制和动态代理

    详解Java中的反射机制和动态代理 什么是反射机制 反射机制是Java语言中的一种机制,它可以在程序运行时获取一个类的信息,包括类的名称、父类、接口、属性、方法等,还可以在运行时获取和设置对象的属性和方法,创建对象并调用方法。 Java中的反射机制主要包括以下几个类: Class:代表一个类,可以获取一个类的信息,如名称、直接父类、实现的接口、构造方法、属性…

    Java 2023年5月20日
    00
  • kafka与storm集群环境的安装步骤详解

    Kafka与Storm集群环境的安装步骤详解 Kafka与Storm是一种在大数据处理及分析领域应用广泛的开源组件,它们分别针对消息队列和流处理进行特性优化设计。在实际使用中,需要将它们结合在一起建立完整的流处理环境。本篇文章将介绍Kafka与Storm集群环境的安装步骤,供读者参考。 硬件环境要求 以下是建立Kafka与Storm集群所需的硬件环境要求: …

    Java 2023年5月20日
    00
  • MyBatis 中 ${}和 #{}的正确使用方法(千万不要乱用)

    下面是详细讲解”MyBatis 中 ${}和 #{}的正确使用方法(千万不要乱用)”的完整攻略。 一、概述 MyBatis是一款基于Java语言的持久层框架,可以将SQL与业务逻辑分离,使得代码更加清晰易读,此外,MyBatis还提供了升级数据库方面的支持,无需编写太多的SQL脚本,MyBatis的性能表现也非常不错。而在MyBatis中,SQL语句连接参数…

    Java 2023年5月20日
    00
  • 如何用Java Stream写出既高雅又装*的代码

    如何用Java Stream写出既高雅又装*的代码? Java Stream可以被用来解决很多问题,从简单的过滤到复杂的组合操作。它极大地减少了编写的代码量,提高了代码的可读性、可维护性和可重用性。 下面是一些使用Java Stream的技巧,可以让你写出高雅又装*的代码。 1. 使用Lambda表达式写过滤器 传统的Java代码需要明确指定每一步操作的细节…

    Java 2023年5月26日
    00
  • Spring MVC参数校验详解(关于`@RequestBody`返回`400`)

    关于Spring MVC参数校验,可以分为两种情况讨论:针对普通请求参数的校验和针对请求体中的JSON格式数据的校验。这里我们主要讲解后者,即针对@RequestBody注解返回400错误时的问题。 1. 报错原因 在开发中,当我们使用@RequestBody注解接收请求体中的JSON格式数据时,经常会遇到传入的参数格式不正确的情况,比如类型不匹配、缺失必要…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部