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操作json对象出现StackOverflow错误的问题及解决

    如果你在 Java 中操作 JSON 对象时遇到 StackOverflow 错误,可能是因为实体类中的字段中包含了一个指向同一类型的对象,而这个对象又有一个指向同一类型的对象……以此类推,最终导致了无限循环。这将导致无限递归,直到抛出 StackOverflow 错误。 解决这种情况的最简单方式是使用“@JsonManagedReference”和…

    Java 2023年5月26日
    00
  • 详解快速排序算法中的区间划分法及Java实现示例

    区间划分法是快速排序算法中一个非常重要的步骤。下面我将详细讲解区间划分法的实现过程,并给出Java实现示例。 区间划分法 简介 区间划分法是快速排序算法的一个核心步骤,其目的是将一个数组以某个值为分界点,将其分为两个部分,其中一个部分所有元素均小于等于该值,另一个部分所有元素均大于等于该值。完成区间划分后,可通过递归地对两个部分分别进行排序,最终完成整个数组…

    Java 2023年5月19日
    00
  • Java Apache Commons报错“ConfigurationException”的原因与解决方法

    当使用Java的Apache Commons类库时,可能会遇到“ConfigurationException”错误。这个错误通常由以下原因之一起: 配置文件错误:如果配置文件错误,则可能会出现此错误。在这种情况下,需要检查配置文件以解决此问题。 配置项缺失:如果配置项缺失,则可能会出现此错误。在这种情况下,需要检查配置项以解决此问题。 以下是两个实例: 例1…

    Java 2023年5月5日
    00
  • Java欧拉函数的计算代码详解

    首先介绍下欧拉函数的定义: 欧拉函数,又称为“φ函数”,表示小于等于n的正整数中有多少个与n互质。记做φ(n)。 Java中计算欧拉函数的代码如下(假设要计算的数为n): public static int eulerFunction(int n) { int res = n; for (int i = 2; i * i <= n; i++) { if…

    Java 2023年5月26日
    00
  • mybatis 自定义实现拦截器插件Interceptor示例

    下面是详细讲解“mybatis 自定义实现拦截器插件Interceptor示例”的完整攻略: 什么是MyBatis拦截器? MyBatis 拦截器是一种插件技术,可自定义MyBatis框架自身的行为,是MyBatis框架中的重要组成部分。MyBatis 内置提供了多种拦截器,例如 Executor、StatementHandler 等,每种拦截器都实现了不同…

    Java 2023年5月20日
    00
  • Jenkins使用Gradle编译Android项目详解

    Jenkins使用Gradle编译Android项目详解 前言 Jenkins是一个功能强大的自动化构建工具,当它和Gradle结合在一起时,可以更方便高效地构建Android项目。本文将详细讲述如何使用Jenkins和Gradle完成Android项目的自动化构建流程。 环境准备 JDK(建议使用8以上版本) Gradle(建议使用5.0以上版本) Jen…

    Java 2023年5月26日
    00
  • IntelliJ IDEA maven 构建简单springmvc项目(图文教程)

    以下是关于“IntelliJ IDEA maven 构建简单springmvc项目(图文教程)”的完整攻略,其中包含两个示例。 IntelliJ IDEA maven 构建简单springmvc项目(图文教程) IntelliJ IDEA是一款强大的Java集成开发环境,它可以帮助我们快速构建Java应用程序。Maven是一款强大的项目管理工具,它可以帮助我…

    Java 2023年5月17日
    00
  • 浅谈java 数据处理(int[][]存储与读取)

    浅谈Java数据处理(int[][]存储与读取) 在Java中,数组是我们常用的数据结构之一。在某些场景下,我们需要处理的数据可能是一个二维数组,本篇文章将会讲解如何处理这种数据结构,包括如何存储和读取。 存储二维数组 Java中的二维数组可以使用 int[][] 来定义,其可以表示一个矩阵。我们可以通过以下代码来定义一个二维数组: int[][] matr…

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