Spring Security 构建rest服务实现rememberme 记住我功能

让我来详细讲解一下如何利用Spring Security构建REST服务实现记住我(remember-me)功能。

什么是记住我功能?

记住我是一个常见的Web应用程序功能,允许用户在关闭并重新打开浏览器后继续使用应用程序而无需重新登录。通常,当用户登录时,他们可以选择“记住我”选项。如果选中此选项,则应用程序将在用户关闭并重新打开浏览器时,使用之前提供的凭据进行自动登录。

实现过程

下面将分为5步来实现Spring Security的记住我功能。

1. 添加Spring Security依赖

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

2. 配置Spring Security

在这一步中,需要配置Spring Security。首先,要启用remember-me功能:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe(); // 启用remember-me功能
    }
}

上述代码通过rememberMe()启用了Spring Security的remember-me功能。这将启用Cookie的自动创建和使用,以保存已认证的用户之间的状态。

3. 配置“记住我”参数

Spring Security提供了以下“记住我”参数的配置:

  • key:用于加密令牌的密钥,必须是16个字符以上的字符串。
  • tokenValiditySeconds:令牌的有效期,以秒为单位。默认为2周。
  • rememberMeParameter:处理“记住我”请求的参数名。默认为"remember-me"。
  • rememberMeCookieName:用于保存令牌的Cookie的名称。默认为“remember-me”。
  • useSecureCookie:设置是否只发送安全Cookie。默认为false。
  • alwaysRemember:设置是否始终发送“记住我”Cookie,而不是在默认的会话Cookie上添加一个属性。默认为false。

你可以通过rememberMe()方法进行配置:

http
    .rememberMe()
        .key("my-remember-me-key")
        .tokenValiditySeconds(86400) // 一天
        .rememberMeParameter("remember-me")
        .rememberMeCookieName("my-remember-me-cookie")
        .useSecureCookie(true)
        .alwaysRemember(true);

4. 编写登录页面和登录处理程序

在登录页面中包含一个复选框,用户可以使用该复选框选择是否记住他们的登录信息。在登录处理程序中,将使用用户名、密码和remember-me参数来进行身份验证。

以下是一个简单的登录页面和应用程序的登录处理程序:

<html>
    <body>
        <h2>Login</h2>
        <form action="/login" method="post">
            <p>
                <label for="username">Username:</label>
                <input type="text" id="username" name="username"/>
            </p>

            <p>
                <label for="password">Password:</label>
                <input type="password" id="password" name="password"/>
            </p>

            <p>
                <label for="remember-me">Remember me:</label>
                <input type="checkbox" id="remember-me" name="remember-me"/>
            </p>

            <input type="submit" value="Submit"/>
        </form>
    </body>
</html>
@Controller
public class LoginController {

    @GetMapping("/login")
    public String showLoginPage() {
        return "login";
    }

    @PostMapping("/login")
    public String login(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String rememberMe = request.getParameter("remember-me");

        if (username.equals("admin") && password.equals("password")) {
            // 如果成功验证,则创建一个remember-me Cookie
            String rememberMeToken = UUID.randomUUID().toString();
            Cookie rememberMeCookie = new Cookie("remember-me", rememberMeToken);
            rememberMeCookie.setPath("/");
            if (rememberMe != null && rememberMe.equals("on")) {
                rememberMeCookie.setMaxAge(60 * 60 * 24 * 30); // 一个月
            } else {
                rememberMeCookie.setMaxAge(0);
            }
            response.addCookie(rememberMeCookie);
            return "success";
        } else {
            return "error";
        }
    }
}

在上述代码中,login()方法将根据提供的用户名和密码进行身份验证。如果验证成功,则创建一个新的记住我Cookie,并将其添加到HTTP响应中。

5. 验证记住我功能是否正常

在每次访问应用程序时,Spring Security将使用保存在Cookie中的信息来自动登录用户。你可以使用类似于以下Java代码的方法验证它是否正常工作:

public void authenticateWithCookie() {
    RestTemplate restTemplate = new RestTemplate();

    // 创建一个HTTP头,包含一个"remember-me" Cookie
    HttpHeaders headers = new HttpHeaders();
    headers.set("Cookie", "remember-me=my-remember-me-token");

    // 调用受Spring Security保护的REST服务
    ResponseEntity<String> response = restTemplate.exchange(
        "http://localhost:8080/protected",
        HttpMethod.GET,
        new HttpEntity<String>(headers),
        String.class);
    String responseBody = response.getBody();
    System.out.println(responseBody);
}

这个方法将创建一个HTTP头,其中包含一个记住我Cookie。然后,它将调用受Spring Security保护的REST服务,以验证该Cookie是否有效。

示例

示例一:基础REST服务

首先,我们创建一个名为“demo”的Spring Boot项目,并在其中添加以下依赖项:

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

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

接下来,我们可以创建一个名为“HelloController”的REST服务:

@RestController
public class HelloController {

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

    @GetMapping("/protected")
    public String protectedEndpoint() {
        return "This is a protected endpoint!";
    }
}

这将为根路径和受保护的路径提供REST服务。

现在,我们可以在Spring Security配置文件中启用记住我功能:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe();
    }
}

最后,在“login.html”的编写包含“记住我”复选框的登录页面:

<html>
    <body>
        <h2>Login</h2>
        <form action="/login" method="post">
            <p>
                <label for="username">Username:</label>
                <input type="text" id="username" name="username"/>
            </p>

            <p>
                <label for="password">Password:</label>
                <input type="password" id="password" name="password"/>
            </p>

            <p>
                <label for="remember-me">Remember me:</label>
                <input type="checkbox" id="remember-me" name="remember-me"/>
            </p>

            <input type="submit" value="Submit"/>
        </form>
    </body>
</html>

我们的示例一完成了!你现在可以启动应用程序并进行测试。

示例二:用户名密码都存储在数据库

我们还可以使用JDBC存储用户名和密码。首先,我们需要在pom.xml中添加以下依赖项:

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

接下来,我们可以在application.properties中配置我们的数据源:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=create-drop

最后,在Spring Security配置文件中稍作修改:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository()) // 设定tokenRepository
                .tokenValiditySeconds(200000); // 设定token有效期

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery(
                        "SELECT username, password, enabled FROM users WHERE username=?")
                .authoritiesByUsernameQuery(
                        "SELECT username, authority FROM authorities WHERE username=?")
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        return tokenRepository;
    }
}

在这里,我们使用tokenRepository()方法将JdbcTokenRepositoryImpl注入到Spring Security中。这个类是可以持久化记住我的Token的,其默认的数据库表结构是:

CREATE TABLE `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) NOT NULL,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
);

最后,我们需要创建一些用户并赋予权限以供测试。

示例完整代码请参见:https://github.com/Bright-Sky/Spring-Security-Demo。

总结

在本篇文章中,我们讲解了如何使用Spring Security构建Rest服务实现“记住我”(remember-me)功能。我们通过示例说明如何启动基本的REST服务,并使用JDBC存储用户名和密码。如果你想了解更多有关Spring Security的内容,请访问官方文档:https://spring.io/projects/spring-security。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security 构建rest服务实现rememberme 记住我功能 - Python技术站

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

相关文章

  • Java中StringUtils工具类的一些用法实例

    讲解Java中StringUtils工具类用法实例的完整攻略如下: 什么是StringUtils工具类 在Java中,我们经常会遇到对字符串的各种操作,比如:判断字符串是否为空,去除字符串中的空格、特殊字符,将字符串转为大写或小写等等。而StringUtils工具类就是帮助我们完成这些字符串操作的工具类。 StringUtils工具类的常用方法 下面介绍St…

    Java 2023年5月27日
    00
  • 使用smartupload组件实现jsp+jdbc上传下载文件实例解析

    使用smartupload组件实现JSP+JDBC上传下载文件,需要经过以下步骤: 下载SmartUpload组件 从官方网站 http://smartupload.io/ 下载最新版本的SmartUpload组件(smartupload.jar),并将其添加到项目的classpath中。 配置Web.xml 在Web.xml中配置SmartUpload的处…

    Java 2023年6月15日
    00
  • spark rdd转dataframe 写入mysql的实例讲解

    要将Spark RDD转换成DataFrame,并将其写入MySQL,您可以按照以下步骤进行操作: 第1步:导入库 假设您已经在Spark和MySQL上安装了适当的依赖项。在这个例子中,我们将使用Spark Core,Spark SQL和MySQL connector。请确保将这些库导入到您的代码库中。 from pyspark.sql import Spa…

    Java 2023年5月20日
    00
  • 在日志中记录Java异常信息的正确姿势分享

    下面我会根据“在日志中记录Java异常信息的正确姿势”这一话题,提供一个完整的攻略。 什么是Java异常? Java异常是指在程序运行过程中产生的错误或异常状态,Java虚拟机会拦截并报告这些异常。Java异常一般分为两类,Checked异常和Unchecked异常,前者需要在方法签名中声明,后者不需要。 为什么需要将Java异常信息记录在日志中? Java…

    Java 2023年5月20日
    00
  • AndroidHttpClient使用Cookie应用分析

    AndroidHttpClient使用Cookie应用分析 什么是Cookie? 在 Web 开发中,Cookie 是一种常用的技术,可以存储用户的信息,使之可以跟踪用户的在线活动。而在 HTTP 协议中,Cookie 是通过服务器在响应头中发送 Set-Cookie 报文告诉客户端,然后客户端把 Cookie 存储起来,在下次请求时自动发给服务器。 Coo…

    Java 2023年5月30日
    00
  • Hibernate实体对象继承的三种方法

    Hibernate是一款流行的Java ORM框架,它提供了多种映射关系的继承方式,这里我们主要介绍三种实现方式。 单表继承 单表继承,即将继承关系建立在同一张表中,使用一个“discriminator”字段用于区分不同的实体子类。这种继承方式实现简单,对于表中数据量不大的情况适用。 实现方式 使用@Entity注解声明父类,使用@Discriminator…

    Java 2023年5月20日
    00
  • JSP转发和重定向的区别分析

    JSP转发和重定向都是在服务器端进行的页面跳转操作,但是它们有很大的区别。 JSP转发和重定向的区别 1. 请求的处理方式 JSP转发是在服务器端进行请求的处理和转发,客户端的请求URL不会发生改变。服务器会将请求转发给目标页面进行处理。 重定向是通过服务器向客户端返回指定的跳转地址,客户端通过重定向,再重新向服务器发起请求。这时客户端的请求URL会发生改变…

    Java 2023年6月15日
    00
  • struts2+jquery实现ajax登陆实例详解

    我将详细讲解“struts2+jquery实现ajax登陆实例详解”的完整攻略。 1. 前言 本文将介绍如何使用 Struts2 和 jQuery 实现前后端的交互,实现 AJAX 登录功能。 2. 后端代码 2.1 登录 Action 首先,我们需要创建一个登陆的 Action。在 Struts.xml 中配置该 Action 的入口路径。 <act…

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