Spring Boot实现登录注册的三种基本方式

cookie方式实现

使用前端缓存cookie的方式实现,十分不安全

后端:

<dependencies>
    <!-- 其他依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

@Controller
public class LoginController {

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

    @PostMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        HttpServletResponse response) {
        // 进行用户名和密码的验证逻辑

        if (isValidUser(username, password)) {
            // 验证通过,创建一个Cookie保存用户登录信息
            Cookie cookie = new Cookie("user", username);
            cookie.setMaxAge(86400); // 设置Cookie有效期为1天
            response.addCookie(cookie);

            // 重定向到登录成功页面
            return "redirect:/success";
        } else {
            // 验证失败,返回登录页面
            return "redirect:/?error=1";
        }
    }

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

    private boolean isValidUser(String username, String password) {
        // 在实际应用中,这里可以进行用户名和密码的验证逻辑,比如查询数据库或调用API等
        // 这里只是一个示例,始终返回true来模拟验证通过
        return true;
    }
}

前端:

<!DOCTYPE html>
<html>
<head>
  <title>Cookie 示例</title>
</head>
<body>
  <h1>Cookie 示例</h1>

  <script>
    function getCookie(name) {
      const value = "; " + document.cookie;
      const parts = value.split("; " + name + "=");
      if (parts.length === 2) {
        return parts.pop().split(";").shift();
      }
    }

    function setCookie(name, value, days) {
      const date = new Date();
      date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
      const expires = "expires=" + date.toUTCString();
      document.cookie = name + "=" + value + ";" + expires + ";path=/";
    }

    function updateCookie(name, value) {
      document.cookie = name + "=" + value + ";path=/";
    }

    function deleteCookie(name) {
      document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;";
    }

    // 获取Cookie的值
    const username = getCookie("user");
    if (username !== undefined) {
      console.log("用户名:", username);
    } else {
      console.log("用户未登录或没有保存用户的Cookie");
    }

    // 设置Cookie的值
    setCookie("user", "John Doe", 7); // 将用户的登录信息保存到Cookie中,有效期为7天

    // 修改Cookie的值
    updateCookie("user", "Jane Doe"); // 将用户的用户名更新为"Jane Doe"

    // 删除Cookie
    deleteCookie("user"); // 删除名为"user"的Cookie
  </script>
</body>
</html>

session的方式

后端保存会话(redis),前端发信息

<!-- Maven 依赖 -->
<dependencies>
    <!-- Spring Session -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-session</artifactId>
    </dependency>
    <!-- Redis 驱动 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>

# Redis 连接配置
spring.redis.host=localhost
spring.redis.port=6379

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@SpringBootApplication
@EnableRedisHttpSession
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

实现session,Spring 会自动使用 Redis 来管理 HttpSession。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

@RestController
public class MyController {
    @GetMapping("/profile")
    public String getProfile(HttpSession session) {
        // 从会话中获取用户信息
        String username = (String) session.getAttribute("username");
        if (username != null) {
            return "Username: " + username;
        } else {
            return "Not logged in";
        }
    }
}

前端:

// 后端返回的响应中包含 session ID
const sessionID = '1234567890';

// 前端将 session ID 存储在 LocalStorage 中
localStorage.setItem('sessionID', sessionID);

// 发送请求时手动将 session ID 携带在请求头中或请求参数中
fetch('/profile', {
  headers: {
    'Authorization': 'Bearer ' + localStorage.getItem('sessionID')
  }
})
.then(response => response.json())
.then(data => {
  if (data.success) {
    // 成功获取到用户资料信息
    console.log(data);
  } else {
    // 未登录,进行相应处理
    console.log('未登录');
  }
});

jwt方式实现

特点:一次登录,到处畅通。
使用sso微服务去认证,通过后保存token,再次验证时出示凭证即可获取登录信息。
在这里插入图片描述

1. 添加依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.3</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2.controller:

    @RequestMapping("/login")
    public Map<String,String> login(String userName, String password){
        Map<String,String> map=new HashMap<>();
        try{
            String token = Jwts.builder().setSubject(userName) //主题,可以放用户的详细信息
                    .setIssuedAt(new Date()) //token创建时间
                    .setExpiration(new Date(System.currentTimeMillis() + 60000)) //token过期时间
                    .setId("userId") //用户ID
                    //.setClaims(hashMap) //配置角色信息
                    .signWith(SignatureAlgorithm.HS256, "WuHan") //加密方式和加密密码
                    .compact();
          //  System.out.println("token:"+token);
            map.put("code","1");
            map.put("msg","success");
            map.put("token",token);
            map.put("user",userName);
        }catch (Exception e){
            map.put("code","0");
            map.put("msg","fail");
            e.printStackTrace();
        }
        return map;
    }

token示例如下:

token:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4YyIsImlhdCI6MTU5MTE1NDQwNiwiZXhwIjoxNTkxMTU0NDY2LCJqdGkiOiJ1c2VySWQifQ.c7gCDgIQ_I40dIWRxyG4yd1xaZQyWflnC7kX2Uoc9H8

token构成包含三个部分:

  • Header 头部
  • Payload 负载
  • Signature 签名

注意事项:
①根据需求设计过期时间(1秒 =1000 毫秒 )
②因为我把时间设计到token里面了所以你可以测试每次产生的token不一样
③设置userId那一栏-我目前是写死了 setId(“userId”) ,你可以根据需求设计不同的值进去

3.校验Token:

try {
    JwtParser parser = Jwts.parser();
    parser.setSigningKey("WuHan");//解析 要和上面“暗号”一样
    Jws<Claims> claimsJws = parser.parseClaimsJws(token);
    Claims body = claimsJws.getBody();
    String username = body.getSubject();
  //  Object role = body.get("role");

    return true;
} catch (ExpiredJwtException e) {
    e.printStackTrace();
} catch (UnsupportedJwtException e) {
    e.printStackTrace();
} catch (MalformedJwtException e) {
    e.printStackTrace();
} catch (SignatureException e) {
    e.printStackTrace();
} catch (IllegalArgumentException e) {
    e.printStackTrace();
}

setSigningKey()与builder中签名方法signWith()对应,parser中的此方法拥有与signWith()方法相同的三种参数形式,用于设置JWT的签名key,用户后面对JWT进行解析。
isSigned() 校验JWT是否进行签名。方法很简单,以分隔符" . ",截取JWT第三段,即签名部分进行判断。

前端:

 <script type="text/javascript">
     
            $("#login").click(function () {
                var name=$("#userName").val();
                var pwd=$("#password").val();
                $.post("http://localhost:8080/user/login",{userName:name,password:pwd},function(data) {
                    console.log(data);
                    if(data.code=="1"){
                      /*  document.cookie=data.token;*/
                        sessionStorage.setItem("token",data.token);
                        sessionStorage.setItem("user",data.user);
                        window.location.href="index.html";
                    }else{
                        window.location.href="login.html";
                    }
                },"json");
            });   
    </script>
//需要验证token的页面
    <script>
        var data = sessionStorage.getItem("token");
        if(data==null){
            window.location.href="login.html";
        }
    </script>


补充:
window.sessionStorage(session级别):暂时储存,浏览器关闭之后会清除
window.localStorage (namespace级别):本地储存,浏览器关闭之后依旧不会清除,只能人为删除

4.开启登录拦截器

/**
 * 登录拦截
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getParameter("token");
        try {
            JwtParser parser = Jwts.parser();
            parser.setSigningKey("WuHan");
            Jws<Claims> claimsJws = parser.parseClaimsJws(token);
            Claims body = claimsJws.getBody();
            String username = body.getSubject();
            Object role = body.get("role");
            return true;
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
        } catch (UnsupportedJwtException e) {
            e.printStackTrace();
        } catch (MalformedJwtException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

5.加载拦截器

@Configuration
public class AppConfig implements WebMvcConfigurer {

    @Resource
    private LoginInterceptor loginInterceptor;

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //.execudePathPatterns()//可以添加不拦截的地址
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
    }
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
- chapter1:[基本项目构建(可作为工程脚手架),引入web模块,完成一个简单的RESTful API](http://blog.didispace.com/spring-boot-learning-1/) - [使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程](http://blog.didispace.com/spring-initializr-in-intellij/) ### 工程配置 - chapter2-1-1:[配置文件详解:自定义属性、随机数、多环境配置等](http://blog.didispace.com/springbootproperties/) ### Web开发 - chapter3-1-1:[构建一个较为复杂的RESTful API以及单元测试](http://blog.didispace.com/springbootrestfulapi/) - chapter3-1-2:[使用Thymeleaf模板引擎渲染web视图](http://blog.didispace.com/springbootweb/) - chapter3-1-3:[使用Freemarker模板引擎渲染web视图](http://blog.didispace.com/springbootweb/) - chapter3-1-4:[使用Velocity模板引擎渲染web视图](http://blog.didispace.com/springbootweb/) - chapter3-1-5:[使用Swagger2构建RESTful API](http://blog.didispace.com/springbootswagger2/) - chapter3-1-6:[统一异常处理](http://blog.didispace.com/springbootexception/) ### 数据访问 - chapter3-2-1:[使用JdbcTemplate](http://blog.didispace.com/springbootdata1/) - chapter3-2-2:[使用Spring-data-jpa简化数据访问层(推荐)](http://blog.didispace.com/springbootdata2/) - chapter3-2-3:[多数据源配置(一):JdbcTemplate](http://blog.didispace.com/springbootmultidatasource/) - chapter3-2-4:[多数据源配置(二):Spring-data-jpa](http://blog.didispace.com/springbootmultidatasource/) - chapter3-2-5:[使用NoSQL数据库(一):Redis](http://blog.didispace.com/springbootredis/) - chapter3-2-6:[使用NoSQL数据库(二):MongoDB](http://blog.didispace.com/springbootmongodb/) - chapter3-2-7:[整合MyBatis](http://blog.didispace.com/springbootmybatis/) - chapter3-2-8:[MyBatis注解配置详解](http://blog.didispace.com/mybatisinfo/) ### 事务管理 - chapter3-3-1:[使用事务管理](http://blog.didispace.com/springboottransactional/) - chapter3-3-2:[分布式事务(未完成)] ### 其他内容 - chapter4-1-1:[使用@Scheduled创建定时任务](http://blog.didispace.com/springbootscheduled/) - chapter4-1-2:[使用@Async实现异步调用](http://blog.didispace.com/springbootasync/) #### 日志管理 - chapter4-2-1:[默认日志的配置](http://blog.didispace.com/springbootlog/) - chapter4-2-2:[使用log4j记录日志](http://blog.didispace.com/springbootlog4j/) - chapter4-2-3:[对log4j进行多环境不同日志级别的控制](http://blog
### 回答1: Spring Boot 是一个基于 Spring 框架的开源框架,它能够让我们更加快速、方便地构建基于 Spring 的应用程序。在 Spring Boot实现用户认证和授权,可以通过 Spring Security 模块来实现。下面是实现 Spring Boot 登录功能基本步骤: 1. 添加 Spring Security 依赖 在 pom.xml 文件中添加 Spring Security 依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 2. 配置 Spring Security 在应用程序的配置类中,添加以下代码以配置 Spring Security: ``` @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("{noop}password").roles("USER"); } } ``` 在上面的代码中,我们配置了 Spring Security 的行为。我们允许任何人访问应用程序的根路径和 /home 路径,但是其他所有路径都需要经过身份验证。我们还配置了登录和注销的行为。在 configureGlobal 方法中,我们定义了一个用户名为 "user",密码为 "password" 的用户,以及该用户的角色为 "USER"。 3. 创建登录页面 创建一个名为 login.html 的 Thymeleaf 模板,用于显示登录表单。在表单中,我们需要指定用户名和密码的输入字段以及提交按钮。 ``` <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>Login</title> </head> <body> <form th:action="@{/login}" method="post"> <div> <label for="username">Username:</label> <input type="text" id="username" name="username"/> </div> <div> <label for="password">Password:</label> <input type="password" id="password" name="password"/> </div> <button type="submit">Log in</button> </form> </body> </html> ``` 4. 运行应用程序 现在我们可以运行应用程序并访问 /login 路径以查看登录表单。输入我们在 configureGlobal 方法中定义的用户名和密码,然后单击登录按钮即可登录。 ### 回答2: Spring Boot 是一种用于开发 Java 应用程序的框架,它简化了传统 Java 项目的配置和搭建过程。在 Spring Boot实现登录功能可以分为以下几个步骤: 1. 创建用户模型:首先定义一个用户模型,包含用户名和密码字段,可以使用注解 `@Entity` 将其映射为数据库表。 2. 数据库配置:在 `application.properties`(或 `application.yml`)文件中配置数据库连接信息,并创建用于存储用户信息的表。 3. 用户注册:实现一个注册页面,将用户输入的用户名和密码存储到数据库中。 4. 用户登录:实现一个登录页面,用户输入用户名和密码后,与数据库中保存的用户信息进行比对,验证用户登录。 5. 身份验证:为登录成功的用户颁发一个身份凭证(如 JWT),并将其存储在用户的浏览器 cookie 中。 6. 登录状态检查:在需要验证登录状态的接口中,使用拦截器或过滤器来检查用户的身份凭证,确认用户是否已登录。 以上是一个简单的 Spring Boot 登录功能的步骤,实际实现中还可以添加密码加密、注销功能、记住我等功能。同时,还可以借助 Spring Security 这样的安全框架来简化登录功能的开发。最后,为了保证代码的安全性和稳定性,建议进行单元测试和集成测试。 ### 回答3: Spring Boot 是一个用于构建独立的、基于生产级别的 Spring 应用程序的框架。在 Spring Boot 中,实现登录功能主要包括以下几个步骤: 1. 创建登录页面:可以使用前端技术(如 HTML、CSS 和 JavaScript)创建一个用户界面,用于用户输入用户名和密码。 2. 创建后端控制器:在 Spring Boot 中,我们可以创建一个控制器类来处理登录请求。该控制器类可以使用 @RestController 注解来标识,并通过 @RequestMapping 注解来指定处理登录请求的 URL。在控制器中,我们可以获取用户输入的用户名和密码,并进行相应的验证。 3. 实现身份验证:在登录功能中,通常需要对用户输入的用户名和密码进行验证,确保用户提供的凭证是有效的。Spring Boot 提供了许多身份验证相关的功能,如使用 Spring Security 来实现基于角色或权限的访问控制。通过配置 Spring Security,我们可以定义用户身份验证的规则,并在控制器中使用相应的注解进行访问控制。 4. 处理登录结果:在用户输入正确的用户名和密码后,我们需要对登录结果进行处理。在 Spring Boot 中,可以将登录结果返回给前端页面,可以通过注解 @ResponseBody 来将结果作为 JSON 或其他格式返回给前端。 综上所述,登录功能是一个常见的应用程序需求,Spring Boot 提供了许多便捷的工具和功能实现功能。我们可以使用前端技术创建登录页面,通过后端控制器处理登录请求,并使用 Spring Security 进行身份验证和访问控制。最后,将处理结果返回给前端页面。以上就是使用 Spring Boot 实现登录功能基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

源城编程哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值