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日

相关文章

  • 微信小程序 登陆流程详细介绍

    下面是关于”微信小程序 登陆流程详细介绍”的攻略。 微信小程序登陆流程详细介绍 1. 获取用户信息前的流程 在小程序中进行用户登陆需要分为两步走,首先是获取Code,然后再用Code换取session_key和openid: wx.login({ success: res => { // 成功获取到Code const code = res.code …

    Java 2023年5月23日
    00
  • Java如何解析html中的内容并存到数据库详解

    Java解析HTML中内容并存储到数据库的完整攻略 在Java中,我们可以使用Jsoup库来解析HTML内容,并使用Java的数据访问对象(DAO)模式将数据存储到数据库中。 1. 概述 在本篇攻略中,我们将通过抓取一个网站上的新闻列表,并将新闻内容解析并存储到数据库中的方式,介绍Java如何解析HTML中的内容并存储到数据库的完整流程。 2. 抓取和解析网…

    Java 2023年5月20日
    00
  • SpringBoot+Jpa项目配置双数据源的实现

    下面是详细讲解“SpringBoot+Jpa项目配置双数据源的实现”的完整攻略。 一、项目结构 在项目结构上,我们需要将不同的数据源分别放在不同的包下,以避免混淆和管理上的困难。 myproject ├── src │   └── main │   ├── java │   │   └── com.example.myproject │   │   ├── …

    Java 2023年5月20日
    00
  • SpringBoot中事半功倍的工具类合集分享

    对于“SpringBoot中事半功倍的工具类合集分享”的完整攻略,我将按照以下结构进行讲解: 介绍SpringBoot中常用的工具类 数据库操作工具类的使用 Http请求工具类的使用 示例1:使用数据库工具类进行增删改查操作 示例2:使用Http请求工具类进行数据爬取 总结 接下来,让我们一步步来看每一部分的具体内容。 1. 介绍SpringBoot中常用的…

    Java 2023年5月15日
    00
  • 详解IDEA搭建springBoot方式一(推荐)

    下面是详细讲解 “详解IDEA搭建springBoot方式一(推荐)” 的完整攻略: 一、前置准备 安装JDK和IntelliJ IDEA。 确认本地已经安装了maven,并且配置了maven环境变量。 二、创建Spring Boot项目 打开IntelliJ IDEA,选择Create New Project。 在左侧的“Spring Initializr…

    Java 2023年5月15日
    00
  • SpringSecurity OAtu2+JWT实现微服务版本的单点登录的示例

    实现微服务版本的单点登录需要结合SpringSecurity、OAuth2和JWT三个技术点。 首先,关于OAuth2的基础概念和流程可以参考我的博客文章:OAuth2授权模式详解。 接下来就是示例说明: 示例1:SpringBoot微服务注册 在OAuth2客户端程序中添加以下依赖: <dependency> <groupId>or…

    Java 2023年6月3日
    00
  • java二维数组遍历的2种代码

    下面是详细讲解“Java二维数组遍历的2种代码”的完整攻略。 什么是二维数组 二维数组是指数组中包含另一个数组序列的数组。它是一种存储表格数据的有效方式。Java 二维数组是一个矩阵式的数组,数据被组织成了行和列,因此每个元素在矩阵中都有自己的位置。 Java二维数组遍历的2种代码 1. 使用双重for循环遍历 int[][] arr = {{1,2,3},…

    Java 2023年5月27日
    00
  • Java陷阱之assert关键字详解

    Java陷阱之assert关键字详解 引言 在Java程序开发中,assert关键字是一种非常有用的调试和测试工具。它能够帮助我们在程序运行时检查程序中的假设与约束是否被满足,从而及时发现程序中的bug。但是,assert关键字也存在着一些陷阱和误区,如果使用不当,就可能会导致程序出现各种意想不到的问题。本文将详细讲解Java中assert关键字的使用方法、…

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