Java SpringSecurity+JWT实现登录认证

一、什么是Java Spring Security和JWT?

Java SpringSecurity是Spring框架中的一个安全工具,能够提供身份验证、授权、防止csrf攻击等功能;

JWT(JSON Web Token)是一种用于身份验证的开放标准(RFC 7519),它使用JSON格式在网络之间安全地传递信息。JWT具有轻量级、开放性、易于使用和便于传输等特点。

二、Java Spring Security和JWT的使用场景及优势

在一些需要身份验证和授权的应用场景下,Java Spring Security和JWT能够帮助我们快速实现用户登录认证、资源权限的控制等功能,并对业务系统的稳定性、安全性产生积极的影响。

Java Spring Security优势:

1.支持多种身份验证方式

2.支持自定义权限验证

3.提供防御csrf攻击的措施

4.提供了安全的cookie记住我功能

5.扩展性强,易于进行二次开发

JWT优势:

1.轻量级

2.可显示和可扩展

3.不依赖于特定的后端技术栈

4.相对于传统的cookie方式,更安全和可靠

三、Java Spring Security+JWT实现登录认证的具体步骤

1.引入Spring Security和JWT依赖

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>5.3.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>5.3.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2.编写登录认证接口

@RestController
@RequestMapping("/api")
public class LoginController {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtUtil jwtUtil;

    @PostMapping("/login")
    public ResultWrapper login(@RequestBody LoginRequest loginRequest) {
        try {
            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginRequest.getUsername(),
                            loginRequest.getPassword()));
        } catch (BadCredentialsException e) {
            // 捕获登录异常
            return ResultWrapper.failure(ResultCodeEnum.LOGIN_FAILED, e.getMessage());
        }

        // ... 根据登陆用户信息生成jwtToken

        return ResultWrapper.success(token);
    }
}

3.根据登录用户信息生成JwtToken

public class JwtUtil {

    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, userDetails.getUsername());
    }

    private String doGenerateToken(Map<String, Object> claims, String subject) {
        Date now = new Date();
        Date validity = new Date(now.getTime() + JWT_EXPIRATION_MS);

        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(now)
                .setExpiration(validity)
                .signWith(SignatureAlgorithm.HS256, JWT_SECRET)
                .compact();
    }
}

4.编写认证拦截器

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtil jwtUserDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        final String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);

        String username = null;
        String jwtToken = null;
        if (authorizationHeader != null && authorizationHeader.startsWith(TOKEN_PREFIX)) {
            jwtToken = authorizationHeader.substring(7);
            username = jwtUtil.extractUsername(jwtToken);
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
            if (jwtUtil.validateToken(jwtToken, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }
}

5.配置Spring Security

@Configuration
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder)
            throws Exception {
        authenticationManagerBuilder.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable()
                .authorizeRequests().antMatchers("/api/login").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        httpSecurity.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

6.编写示例代码

举个例子,如果你是一个租房网站的开发人员。假设你们的网站首页需要用户登录才能访问,如果用户没有登录,应该跳转到登录页。

示例 1:登录接口

你们的租房网站提供登录接口,需要用户在请求体中传入用户名和密码:

POST /api/login HTTP/1.1
Content-Type: application/json;charset=UTF-8
{
    "username": "example",
    "password": "password"
}

如果用户输入的用户名和密码正确,则响应体中返回JWT Token:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "code": "0",
    "message": "登录成功!",
    "data": "eyJhbG..."
}

示例 2:首页请求

用户在登录成功后,系统将通过JWT Token检验用户的身份,不符合条件的用户将被重定向到登录页:

GET /api/home HTTP/1.1
Authorization: Bearer eyJhbG...

如果JWT Token验证成功,则允许用户访问首页:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "code": "0",
    "message": "欢迎来到我们的租房网站!"
}

以上是Java SpringSecurity+JWT实现登录认证的完整攻略,通过以上流程,您可以成功地将Java SpringSecurity和JWT应用到您的业务系统中,实现用户的安全登录认证。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java SpringSecurity+JWT实现登录认证 - Python技术站

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

相关文章

  • Java CAS机制详解

    Java CAS机制详解 什么是CAS机制 CAS(Compare And Swap),即比较并替换,是一种并发控制方式。它的思想是:当多个线程尝试同时更新某一个内存地址时,只有其中一个线程能更新成功,而其余的线程都需要等待。这种方式在并发编程中是很常见的。 CAS机制是通过硬件保证操作的原子性,来避免线程安全问题。 CAS操作的原理 CAS机制需要涉及到三…

    Java 2023年5月26日
    00
  • Redis集群与SSM整合使用方法

    下面是Redis集群与SSM整合使用方法的完整攻略。 一、Redis集群 1.1 环境搭建 为了搭建Redis集群,我们需要先安装Redis和redis-trib.rb。Redis的下载链接为:https://redis.io/download ,安装好之后将redis-server添加到环境变量中。redis-trib.rb是Redis自带的一个Ruby脚…

    Java 2023年5月19日
    00
  • Struts2学习笔记(4)-通配符的使用

    下面是对于“Struts2学习笔记(4)-通配符的使用”的完整攻略: Struts2学习笔记(4)-通配符的使用 在 Struts2中,我们可以使用通配符来匹配 URL 中的任意部分,这使得我们可以更加灵活地配置我们的 URL 地址。 下面将会分别介绍两种常见的通配符。 通配符 * * 通配符允许匹配任何字符,它通常用于模糊匹配路径名称的一部分。 下面是一个…

    Java 2023年5月20日
    00
  • springboot使用nacos的示例详解

    Spring Boot 使用 Nacos 的示例详解 在本文中,我们将详细介绍如何在 Spring Boot 中使用 Nacos。我们将介绍 Nacos 的概念、配置和使用,并提供两个示例。 Nacos 概念 Nacos 是一个开源的动态服务发现、配置和服务管理平台。Nacos 可以帮助我们快速搭建微服务架构,并提供了许多开箱即用的功能,如服务注册、配置管理…

    Java 2023年5月15日
    00
  • 如何在Java中优雅地判空详解

    如何在Java中优雅地判空详解 在Java开发中,判断对象是否为空是一个非常常见的操作。但是,如果不注意判空的方式和实现,容易导致代码可读性差、冗长、容易出错等问题。本文将介绍几种优雅的判空方式,帮助Java开发者写出更简洁、易读、易维护的代码。 使用Objects工具类 Java8中新增的Objects类提供了一系列静态方法,用于判断对象是否为空。例如: …

    Java 2023年5月26日
    00
  • java实现时间控制的几种方案

    下面我来详细讲解“Java实现时间控制的几种方案”的完整攻略。 一、使用Java自带的Timer和TimerTask类 Java自带了Timer和TimerTask类可以用来实现时间控制。其中,Timer类可以用来定时执行一项任务,而TimerTask类则是表示一个可调度的任务。 使用方法如下: import java.util.Timer; import …

    Java 2023年5月20日
    00
  • 使用Springboot+poi上传并处理百万级数据EXCEL

    下面我将为您详细讲解如何使用Springboot+poi上传并处理百万级数据EXCEL的完整攻略。 1. 准备工作 在使用Springboot+poi上传并处理百万级数据EXCEL前,需要先完成以下准备工作: 确保已经安装好了Java环境,建议使用JDK 1.8及以上版本; 确保已经安装好了Maven,可以通过Maven来管理项目依赖; 需要引入Spring…

    Java 2023年6月3日
    00
  • SpringBoot @PostMapping接收HTTP请求的流数据问题

    要实现SpringBoot @PostMapping接收HTTP请求的流数据,需要遵循以下步骤: 在Controller中添加接口,使用@PostMapping注解,并使用@RequestBody注解请求参数; 创建一个封装流数据的Java对象,并使用@RequestBody注解接收请求参数; 在请求头中添加Content-Type字段,值为applicat…

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