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日

相关文章

  • Spring Boot实现异步请求(Servlet 3.0)

    所需依赖 实现Servlet 3.0异步请求,我们需要添加以下依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </depe…

    Java 2023年6月15日
    00
  • Springboot集成knife4j实现风格化API文档

    下面是“Springboot集成knife4j实现风格化API文档”的完整攻略: 简介 knife4j是为Java Spring项目提供的一款文档生产工具,可以便捷地生成API文档,并支持根据Swagger注解来生成对应的代码实现。knife4j还提供了自定义的UI界面,可以实现API文档的风格化展示。 在本攻略中,我们将介绍如何在Springboot项目中…

    Java 2023年5月19日
    00
  • 基于Security实现OIDC单点登录的详细流程

    下面是基于Security实现OIDC单点登录的详细流程: 1. 环境准备 首先,要在项目中添加Spring Security和Spring Security OAuth2依赖: <dependency> <groupId>org.springframework.security</groupId> <artifac…

    Java 2023年5月20日
    00
  • Java调用Shell命令和脚本的实现

    Java调用Shell命令和脚本是一种常见的技术,可以为开发人员带来更灵活的开发方式。在这里,我们将详细讲解Java调用Shell命令和脚本的实现攻略。 什么是Shell命令和脚本 Shell命令和脚本都是运行在Linux/Unix系统上的脚本语言。Shell命令是一种命令行工具,用于在终端中实现系统管理任务。Shell脚本是一种执行自动化任务的脚本文件,可…

    Java 2023年5月26日
    00
  • spring boot项目使用@JsonFormat失效问题的解决

    问题描述: 在Spring Boot项目中,使用@JsonFormat注解时,时间格式化不起作用,导致返回的时间格式不符合要求。如何解决这一问题? 解决方案: 引入依赖 首先,在项目的pom.xml文件中,引入以下依赖: <dependency> <groupId>com.fasterxml.jackson.datatype</…

    Java 2023年5月26日
    00
  • 用Java连接sqlserver数据库时候几个jar包的区别分析

    用Java编程语言连接SQL Server数据库时,需要使用特定的JDBC(Java数据库连接)驱动程序。在使用JDBC驱动程序时,需要引入相应的jar包。本文将为您介绍在连接SQL Server数据库时使用的几个jar包,并对它们的区别进行分析。 1. jtds.jar jtds.jar是连接SQL Server数据库时最常使用的jar包之一。它是一个纯J…

    Java 2023年5月20日
    00
  • Spring Boot Maven Plugin打包异常解决方案

    下面我来详细讲解如何解决“Spring Boot Maven Plugin打包异常”的问题。 问题描述 在使用Spring Boot Maven Plugin打包时,有时可能会遇到如下异常: [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.3…

    Java 2023年5月26日
    00
  • JAVA 十六进制与字符串的转换

    Java 中可以通过多种方式实现十六进制和字符串之间的转化。本文将介绍两种主要的方法:使用内置类库和字节数组转换。 使用内置类库实现 Java 内置的 Integer、Long 和 Short 等类库提供了十六进制和字符串之间的转化方法。下面是一个示例: // 十六进制转字符串 int hexVal = 0x1F; String hexStr = Integ…

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