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日

相关文章

  • SpringBoot配置log4j输出日志的案例讲解

    下面我将详细讲解如何配置log4j输出SpringBoot日志的案例攻略。 1. 引入log4j依赖 在pom.xml文件中,我们需要引入log4j的依赖,如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sprin…

    Java 2023年5月26日
    00
  • ESC之ESC.wsf可以实现javascript的代码压缩附使用方法第1/5页

    ESC之ESC.wsf可以实现javascript的代码压缩附使用方法 什么是ESC和ESC.wsf? ESC是一种单向加密机制,其全称为“Escape Sequence”,中文意思是“转义序列”。当一个字符在普通字符串中使用特定编码表示时,它就成为了转义字符,在JavaScript中常被用来表示特殊字符或者格式化字符串等。 而ESC.wsf则是一种通用的脚…

    Java 2023年6月15日
    00
  • Springboot中静态文件的两种引入方式总结

    下面是详细的“Springboot中静态文件的两种引入方式总结”的攻略: 1. 静态文件的常规引入方式 在Springboot项目中,我们可以将静态文件放置在项目的“resources/static”目录下,这些文件就可以被访问到。 在html文件中,我们可以用如下代码来引入静态文件: <link rel="stylesheet" …

    Java 2023年5月20日
    00
  • 如何使用Java模拟退火算法优化Hash函数

    使用Java模拟退火算法优化Hash函数的完整攻略如下: 1. 了解退火算法基本原理 退火算法来源于物理学中的热力学原理,这个算法模拟了物质从高温到低温的过程,利用了概率方法找到全局最优解。 退火算法的基本步骤如下: 初始化温度和初始状态 外层循环直到达到停止条件 内层循环直到达到迭代条件 在当前状态的邻域内随机选择一个新状态 计算新状态的能量 判断是否接受…

    Java 2023年5月19日
    00
  • SpringBoot常用计量与bean属性校验和进制数据转换规则全面分析

    SpringBoot常用计量与bean属性校验和进制数据转换规则全面分析 1. 前言 SpringBoot是一个快速开发框架,它为我们提供了丰富的自动化配置,可让我们快速构建应用程序。在SpringBoot中使用一些常用的类,如计量单位、属性校验和进制数据转换,可以加快开发速度,减少开发者的重复劳动。本攻略将会详细讲解SpringBoot常用计量与bean属…

    Java 2023年5月20日
    00
  • Spring-data-redis操作redis知识总结

    Spring-data-redis操作redis知识总结 Spring-data-redis是Spring Framework提供的针对Redis的功能性扩展,支持面向对象、具有一致抽象的Redis数据访问技术。本文将重点介绍Spring-data-redis操作Redis的相关知识总结。 Spring-data-redis操作Redis的基本步骤 添加Re…

    Java 2023年5月20日
    00
  • JSP编译指令page、include详解

    让我们开始讲解JSP编译指令page、include的详解。 一、JSP编译指令page 什么是JSP编译指令page JSP编译指令page,就是使用<%@ page%>标签来声明JSP页面的属性和配置。它通常位于JSP页面的头部,用于设置页面的各种属性,如页面字符集、session是否启用等等。 page指令语法及格式 page指令语法格式如…

    Java 2023年6月15日
    00
  • Java SimpleDateFormat与System类使用示例详解

    Java SimpleDateFormat与System类使用示例详解 SimpleDateFormat类 SimpleDateFormat是Java中用于格式化和解析日期的类,可以将日期转换为指定格式的字符串,也可以将指定格式的字符串转换为日期对象。 格式化日期 以下是一个将日期格式化为指定格式字符串的示例: import java.text.Simple…

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