Java SpringSecurity+JWT实现登录认证

yizhihongxing

下面我将为你详细讲解“Java SpringSecurity+JWT实现登录认证”的完整攻略。 首先,让我们一步步来实现一个基于SpringSecurity和JWT的用户登录认证系统。整个实现过程包括三个步骤:

  1. 集成SpringSecurity和JWT
  2. 配置SpringSecurity
  3. 实现登录接口

接下来,我们将分别对这三个步骤进行讲解。

1. 集成SpringSecurity和JWT

我们使用Maven来管理项目依赖,因此需要在pom.xml文件中添加如下两个依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.2</version>
</dependency>

上述依赖中,spring-boot-starter-security是SpringSecurity的启动器,jjwt-api是JWT的API。

接下来,我们需要创建一个JWT工具类,用于生成和解析JWT,实现代码如下:

@Component
public class JwtTokenUtil {
    private final String secret = "mySecret";
    private final long expiration = 604800L;

    public String generateToken(String username) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("sub", username);
        claims.put("created", new Date());
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    public String getUsernameFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
        return claims.getSubject();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
            return true;
        } catch (ExpiredJwtException ex) {
            System.out.println("Token已过期");
        } catch (SignatureException ex) {
            System.out.println("Token签名错误");
        } catch (JwtException ex) {
            System.out.println("Token解析错误");
        } catch (Exception ex) {
            System.out.println("其他错误");
        }
        return false;
    }
}

上述代码中,核心的三个方法分别是:generateToken用于生成JWT,getUsernameFromToken用于从JWT中获取用户名,validateToken用于验证JWT是否有效。

2. 配置SpringSecurity

接下来,我们需要配置SpringSecurity,添加一个SecurityConfiguration类,实现代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterBefore(new JwtAuthenticationFilter(jwtTokenUtil), UsernamePasswordAuthenticationFilter.class);
    }
}

上述代码中,我们通过auth.inMemoryAuthentication()方式添加了一个用户,用户名为user,密码为password,角色为USER。configure(HttpSecurity http) 方法用于配置访问规则,我们允许/api/login接口不需要认证,其他接口需要进行认证。sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)方法用于设置Session的创建策略为不创建Session。

3. 实现登录接口

最后,我们需要实现一个/login接口,用于接受用户的用户名和密码,生成JWT,并返回给客户端。实现代码如下:

@RestController
@RequestMapping("/api")
public class LoginController {
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ResponseEntity<?> login(@RequestParam("username") String username, @RequestParam("password") String password) {
        Authentication authentication = null;
        try {
            authentication = new UsernamePasswordAuthenticationToken(username, password);
            authentication = authenticationManager().authenticate(authentication);
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse(false, "用户名或密码错误"));
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = jwtTokenUtil.generateToken(username);
        return ResponseEntity.ok(new JwtAuthenticationResponse(token));
    }

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

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

    @Autowired
    private UserDetailsService userDetailsService;
}

上述代码中,我们通过/login接口接受到的用户名和密码,创建一个UsernamePasswordAuthenticationToken对象,并调用authenticationManager().authenticate(authentication)方法进行认证,如果认证成功,则生成JWT,并返回给客户端。

至此,我们就完成了一个基于SpringSecurity和JWT的用户登录认证系统。

下面,我来介绍两条关于该系统的使用示例:

  1. 使用Postman进行登录认证

在Postman中发送如下请求:

URL: http://localhost:8080/api/login
Method: POST
Body: x-www-form-urlencoded
- username: user
- password: password

可以得到如下JSON响应:

{
"token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNTkyNTIyNzg5LCJleHAiOjE1OTMxMDcyODl9.pjLckrJZL98QXFJ8UDrD7lmlfvI7GcJBAc5FAwVV-easGnaC1z-cQZ7zk4-tjOq7kQZN5yYBLaX10KjcOjSDcA"
}

可以看到,我们成功地获得了JWT。

  1. 使用SpringBoot集成测试进行登录认证

在创建SpringBoot集成测试时,需要在测试类上添加注解@WebMvcTest,用于启用Spring的Web应用程序上下文,同时会自动配置SpringMvc相依的Bean。

@RunWith(SpringRunner.class)
@WebMvcTest
public class LoginControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private JwtTokenUtil jwtTokenUtil;

    @Test
    public void testLoginSuccess() throws Exception {
        when(jwtTokenUtil.generateToken(any())).thenReturn("test_token");
        String requestBody = "{\"username\":\"user\",\"password\":\"password\"}";
        mockMvc.perform(post("/api/login")
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestBody))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.token", is("test_token")));
    }

    @Test
    public void testLoginFailure() throws Exception {
        String requestBody = "{\"username\":\"user\",\"password\":\"error_password\"}";
        mockMvc.perform(post("/api/login")
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestBody))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.success", is(false)))
                .andExpect(jsonPath("$.message", is("用户名或密码错误")));
    }
}

上述代码中,我们通过MockMvc对象模拟了一个HTTP请求,发送给/login接口,通过when(jwtTokenUtil.generateToken(any())).thenReturn("test_token")模拟了一个JWT。执行两个测试用例,分别测试了登录成功和登录失败的情况。

希望我的讲解可以帮助到你。

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

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • 流式图表拒绝增删改查之框架搭建过程

    框架搭建过程可以分为以下几个步骤: 步骤一:确定需求和技术栈 首先需要明确项目的需求和技术栈。比如需要开发一个流式图表的应用,支持数据的实时更新和展示。技术栈可以选择 React,D3.js 等前端技术。如果需要后端支持,可以选择 Node.js,Python 等后端技术。 步骤二:搭建项目结构 接下来需要搭建项目的基本结构。可以使用 create-reac…

    Java 2023年5月20日
    00
  • spring boot教程之产生的背景及其优势

    Spring Boot教程之产生的背景及其优势 产生背景 在传统的Java Web开发过程中,我们需要编写大量的配置文件,比如web.xml、spring.xml等。而随着技术的不断发展,Java Web开发过程中出现了很多新的框架,比如Spring、Spring MVC、Hibernate等。但是这些框架的集成配置却比较麻烦,需要编写大量XML配置文件。因…

    Java 2023年5月15日
    00
  • Java Kafka 消费积压监控的示例代码

    Java Kafka消费积压监控是Kafka中比较常见的需求之一。本文将介绍如何使用Java代码实现Kafka消费积压监控,并提供两个示例。 准备工作 在开始实现Java Kafka消费积压监控之前,请确保你已经完成以下准备工作: 安装Java开发环境和Maven构建工具。 安装Kafka,并启动Kafka服务。 创建一个Kafka主题,并开始往Kafka主…

    Java 2023年5月20日
    00
  • Java使用application.property读取文件里面的值

    当我们开发Java Web 应用时,经常需要从配置文件中读取一些参数,这里我们将详细讲解如何使用 application.properties 文件来读取配置值。 1. 创建配置文件 我们首先需要创建一个 application.properties文件,该文件是Spring Boot标准的配置文件,实际上Spring Boot中有多种方式配置应用程序,如a…

    Java 2023年5月19日
    00
  • Scala文件操作示例代码讲解

    我们来详细讲解一下“Scala文件操作示例代码讲解”的完整攻略。 概述 在Scala程序中,文件操作是非常常见的操作。Scala提供了一些简单易用的API帮助我们在程序中进行文件操作。本攻略将会详细讲解如何在Scala程序中进行简单的文件操作,包括如何读取文件、写入文件、拷贝文件和删除文件。 读取文件 Scala的io包中提供了File类,可以用来表示文件或…

    Java 2023年5月20日
    00
  • 如何使用Java ORM框架?

    使用Java ORM框架可以方便地将关系型数据库的数据映射到Java对象中。下面详细讲解如何使用Java ORM框架。 步骤一:选择一个Java ORM框架 Java ORM 框架有很多,如Hibernate、MyBatis、Spring Data JPA等。在选择时需考虑框架的功能、性能和学习难度等因素。 在本次攻略中,我们以Hibernate作为示例。 …

    Java 2023年5月11日
    00
  • Java 面向对象通过new揭开对象实例化

    关于“Java 面向对象通过new揭开对象实例化”的攻略,我来给您讲解一下。 1. 对象实例化 在Java中,创建一个对象本质上就是实例化一个类,这个类可以理解为对象的模板。实例化类使用的关键字为 new。使用 new 关键字可以在内存中实例化一个对象,并返回一个指向该对象的引用。 示例代码: public class Car { public String…

    Java 2023年5月26日
    00
  • java的Hibernate框架报错“QueryException”的原因和解决方法

    当使用Hibernate框架时,可能会遇到“QueryException”错误。这个错误通常是由于以下原因之一引起的: HQL语句错误:如果您的HQL语句存在问题,则可能会出现此错误。在这种情况下,需要检查您的HQL语句并确保它们正确。 参数绑定错误:如果您的参数绑定存在问题,则可能会出现此错误。在这种情况下,需要检查您的参数绑定并确保它们正确。 数据库表结…

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