SpringBoot和Redis实现Token权限认证的实例讲解

下面我会为您介绍如何使用Spring Boot和Redis实现Token权限认证。

为什么使用Token认证?

在Web应用程序中,为了保护页面和API,需要用户进行登录并验证其身份。其中一种常用的方法是使用Token认证。在Token认证中,用户首先输入用户名和密码进行登录,验证成功后,服务器会返回一个Token令牌,将其存储在客户端。随后,客户端将该Token在每次请求时发送给服务器,服务器会解码Token并验证是否有效,从而决定是否授权该操作。

Token认证的优点包括:

  • 不需要存储Session状态,因此可以扩展到多台服务器集群。
  • 客户端可以自主管理Token,不需要强制退出。
  • 可以支持不同的身份验证策略(例如直接验证或者OAuth认证)。

实现流程

接下来我们将使用SpringBoot和Redis实现Token权限认证,实现的流程如下:

  1. 用户输入用户名和密码进行登录。
  2. 服务器验证用户名和密码是否正确。
  3. 若验证成功,则生成一个Token并存储在Redis中。
  4. 服务器将该Token返回给客户端。
  5. 客户端在每次请求时将该Token作为HTTP头部的Authorization属性值发送给服务器。
  6. 服务器解析该Token,并验证其有效性。
  7. 验证成功后,服务器授权该操作。

实现步骤

1. 创建Spring Boot项目

首先,我们需要创建一个Spring Boot项目。可以使用https://start.spring.io/创建项目。本例中,我们需要选中Web、Redis和Security模块。

2. 创建一个登录页面

在src/main/resources/templates目录下,创建一个login.html文件,用于显示登录页面。以下是该文件的代码:

<!DOCTYPE html>
<html>
    <head>
        <title>登录</title>
    </head>
    <body>
        <div>
            <h3>登录</h3>
            <form method="post" action="/login">
                <div>
                    <label for="username">用户名:</label>
                    <input type="text" id="username" name="username">
                </div>
                <div>
                    <label for="password">密码:</label>
                    <input type="password" id="password" name="password">
                </div>
                <div>
                    <button type="submit">登录</button>
                </div>
            </form>
        </div>
    </body>
</html>

3. 创建一个登录Controller

在src/main/java目录下,创建一个名为LoginController的类,用于处理用户登录请求。以下是该类的代码:

@RestController
public class LoginController {
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestParam String username,
                                         @RequestParam String password) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);

        if (userDetails == null || !passwordEncoder.matches(password, userDetails.getPassword())) {
            return new ResponseEntity<>("用户或密码不正确", HttpStatus.FORBIDDEN);
        }

        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, username);

        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", token);

        return new ResponseEntity<>(headers, HttpStatus.OK);
    }
}

首先,该类使用@Autowired注解自动注入了UserDetailsService、PasswordEncoder和StringRedisTemplate对象。

在login方法中,通过调用userDetailsService对象的loadUserByUsername方法,获取用户对应的UserDetails对象。接着,通过调用passwordEncoder对象的matches方法,比较用户输入的密码和UserDetails对象中的密码是否匹配。

如果匹配失败,返回HTTP状态码403。如果匹配成功,生成一个唯一的Token(使用UUID),将用户名和Token存储在Redis中。最后,依照HTTP协议规范,将这个Token作为HTTP头部的Authorization属性值返回给客户端。

4. 创建Token过滤器

在src/main/java目录下,创建一个名为TokenFilter的类,用于拦截客户端请求并验证是否有权限进行该操作。以下是该类的代码:

public class TokenFilter extends OncePerRequestFilter {
    private static final String HEADER_AUTHORIZATION = "Authorization";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(HEADER_AUTHORIZATION);
        if (token != null) {
            String username = redisTemplate.opsForValue().get(token);
            if (username != null) {
                SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList()));
            }
        }

        filterChain.doFilter(request, response);
    }
}

首先,该类使用@Autowired注解自动注入了StringRedisTemplate对象。

在doFilterInternal方法中,该过滤器会从请求头部中获取Authorization属性值(即Token)。接着,它会使用这个Token从Redis中获取对应的用户名。如果找到了用户名,就将该用户名存入SecurityContext中,并授权该操作。

5. 配置Security

在src/main/java目录下,创建一个名为SecurityConfig的类,用于配置Spring Security。以下是该类的代码:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests().anyRequest().authenticated()
                .and().addFilterBefore(new TokenFilter(), UsernamePasswordAuthenticationFilter.class)
                .formLogin().loginPage("/login").loginProcessingUrl("/login").permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }
}

首先,该类使用@Autowired注解自动注入了UserDetailsService和PasswordEncoder对象。

在configure方法中,该类关闭了CSRF保护,并允许所有请求进行身份验证。接着,它添加了一个TokenFilter过滤器,并将其放在了UsernamePasswordAuthenticationFilter过滤器之前。最后,它配置了一个form表单进行登录,并指定了登录页面的地址。

在configure(AuthenticationManagerBuilder auth)方法中,该类将自定义的UserDetailsService以及PasswordEncoder注册到了AuthenticationManagerBuilder中。

6. 创建测试Controller

在src/main/java目录下,创建一个名为TestController的类,用于测试Token认证是否生效。以下是该类的代码:

@RestController
public class TestController {
    @GetMapping("/hello")
    public String hello() {
        return "hello, world!";
    }
}

7. 配置Redis

在src/main/java目录下,创建一个名为RedisConfig的类,用于配置Redis连接。以下是该类的代码:

@Configuration
public class RedisConfig {
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory("localhost", 6379);
    }

    @Bean
    public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        return template;
    }

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(connectionFactory);
        return template;
    }
}

这个类使用@Bean注解声明了一个RedisConnectionFactory对象,并将其连接到了本地的6379端口。接着,声明了redisTemplate和stringRedisTemplate对象,并将其注册到Spring IoC容器中。

8. 测试

至此,我们已经完成了所有的代码编写。现在可以启动应用程序,并访问http://localhost:8080/login页面。输入用户名和密码后,将返回一个Token。使用Postman或者浏览器发送一个HTTP GET请求到http://localhost:8080/hello,将Authorization属性设置为该Token即可。如果Token验证通过,将返回"hello, world!"字符串。

示例1:curl测试http://localhost/login登录,并返回token

curl --location --request POST 'http://localhost:8080/login' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=admin' \
--data-urlencode 'password=admin'

输出:
"Authorization: c4852673-a86f-4c18-a5ae-54494ca9a1b3"

示例2:使用curl测试http://localhost/hello

curl --location --request GET 'http://localhost:8080/hello' \
--header 'Authorization: c4852673-a86f-4c18-a5ae-54494ca9a1b3'

输出:
"hello, world!"

综上所述,以上就是使用SpringBoot和Redis实现Token权限认证的实例讲解,包括了创建登录页面、创建登录Controller、创建Token过滤器、配置Security、创建测试Controller、配置Redis、测试Token认证等多个步骤。通过学习本文,读者可以了解到如何使用Spring Boot和Redis搭建一个Token认证服务,并在Web应用程序中进行使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot和Redis实现Token权限认证的实例讲解 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java实现简单计算器小程序

    Java实现简单计算器小程序攻略 1. 准备工作 在开始编写代码前,需要先安装Java开发环境(JDK)和集成开发工具(IDE)。 可以通过以下步骤安装JDK和IDE: 下载并安装JDK。可以从官网下载JDK的安装包,下载完后按照提示进行安装,并配置环境变量。 JDK官网:https://www.oracle.com/java/technologies/ja…

    Java 2023年5月23日
    00
  • Java之int和string类型转换详解

    本文将为大家详细讲解Java中int和String类型之间的转换方法及应用场景。 一、从int转换为String 在Java中,将int类型转为String类型可以通过以下两种方式实现: 1. 使用String类的valueOf()方法 int num = 123; String str = String.valueOf(num); 2. 使用Integer…

    Java 2023年5月27日
    00
  • 详解Java如何实现一个像String一样不可变的类

    要实现一个像String一样不可变的Java类,包括以下几个步骤: 1. 将类声明为final和所有字段声明为private public final class ImmutableClass { private final String field1; private final int field2; public ImmutableClass(Stri…

    Java 2023年5月26日
    00
  • Springboot 如何关闭自动配置

    关闭Spring Boot自动配置的方式主要有以下两种: 使用exclude属性 Spring Boot允许我们通过在@EnableAutoConfiguration注解上使用exclude属性来禁用某些自动配置类。我们可以指定一个或多个自动配置类,以便在Spring Boot的启动过程中被排除。例如: @SpringBootApplication(excl…

    Java 2023年5月20日
    00
  • 虚拟机的类型有哪些?

    以下是关于虚拟机类型的完整使用攻略: 虚拟机的类型 虚拟机可以分为以下几种类型: 桌面虚拟:桌面虚拟机是一种在个人计算机上运行的虚拟机,它可以模拟多个操作系统和应用程序,从而提供更好的资源利用率和更好的安全性。常见桌面虚拟机软件包括VirtualBox、VMware Workstation等。 服务器虚拟机:服务器虚拟机是一种在服务器上运行虚拟机,它可以将一…

    Java 2023年5月12日
    00
  • java应用领域分析

    Java应用领域分析是指对Java应用程序的具体业务场景和需求进行细致的分析和了解,以便更好地开发出符合用户需求的Java应用,具体的攻略步骤如下: 1.需求调研 首先需要充分调研客户的需求,收集相关业务场景信息和运营数据,包括产品功能、用户痛点、市场趋势、用户体验、业务流程等,为后续的分析和设计提供数据支持。 2.业务分析 在收集完用户需求后,需要对需求进…

    Java 2023年5月20日
    00
  • Tomcat之web应用的目录组成结构_动力节点Java学院整理

    以下是详细的攻略。 1. 概述 在使用Tomcat进行Web开发时,每个Web应用程序都有特定的目录结构。在这个目录结构中,存放了Web应用程序相关的文件,包括Web应用程序的资源、配置文件、class文件、静态文件等。在进行Web应用的开发和部署时,了解这些文件所在的目录结构是非常重要的。 2. 目录结构 在Tomcat中,每个Web应用程序都必须有一个独…

    Java 2023年6月2日
    00
  • Java基础之Maven详解

    Java基础之Maven详解 什么是Maven? Maven 是一个项目建立,依赖管理以及项目生命周期管理的工具。使用 Maven 可以很方便地构建、打包、发布和管理 Java 项目。 Maven的工作原理 Maven 的工作原理是:在项目的根目录创建一个名为 pom.xml 的文件,它是 Maven 的核心文件,其中定义了以下信息: 项目的基本信息,比如名…

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