针对“Springboot集成Spring Security实现JWT认证的步骤详解”这个主题,我将从以下几个方面给出详细的解答:
-
Spring Security、JWT和Spring Boot的基本概念介绍
-
JWT认证的基本过程及原理
-
Springboot集成Spring Security实现JWT认证的步骤详解
-
两个示例:
a. 基于用户名密码认证,返回JWT
b. 基于JWT认证,保护REST API接口
以下是详细的内容:
一、Spring Security、JWT和Spring Boot的基本概念介绍
1. Spring Security
Spring Security 是 Spring 提供的安全框架,它能够帮助我们在 Spring 应用中实现许多安全功能,例如:身份验证、授权、防止 XSS 攻击、CSRF 攻击等。
2. JWT
JWT ( JSON Web Token ) 是一个基于 JSON 的开放标准(RFC 7519),用于在两个实体之间传递安全信息。JWT通常被用来实现身份认证和授权。当用户通过认证时,系统会生成一段 JWT,将其发送给客户端。客户端在请求时需要将该 JWT 传给服务端,服务端可以解析 JWT 来校验身份信息的合法性。
3. Spring Boot
Spring Boot是一个基于Spring框架的快速开发开发框架。它可以帮助开发者快速搭建Spring应用,同时提供了很多开箱即用的组件(例如:Tomcat、Jackson、Hibernate、Spring Data、Spring Security等),减少了开发者的开发成本。
二、JWT认证的基本过程及原理
JWT 由三部分组成:头部、载荷和签名。头部和载荷使用 Base64 编码,编码后的字符串在 HTTP 响应头的 Authorization 字段或者 HTTP 请求体中传递。签名用于校验 JWT 的合法性。
JWT 认证的基本过程如下:
-
客户端通过用户名和密码向服务端请求认证。
-
服务端校验用户名和密码,如果校验通过则生成一个 JWT。
-
服务端将生成的 JWT 发送给客户端。
-
客户端在每次请求中需要在 Authorization 字段中携带 JWT。
-
服务端会在每次接收到请求时校验 JWT 的合法性,如果合法则允许请求,否则返回 401 错误码。
三、Springboot集成Spring Security实现JWT认证的步骤详解
1. 添加Spring Security及JWT依赖
<dependencies>
<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>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
2. 编写认证过滤器
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public static final String JWT_SECRET = "mysecretkey";
public static final long JWT_EXPIRATION_TIME = 864_000_000; // 10 days
private final AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
try {
UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
new ArrayList<>()
)
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token = Jwts.builder()
.setSubject(((User) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, JWT_SECRET.getBytes())
.compact();
response.addHeader("Authorization", "Bearer " + token);
}
}
3. 添加Security配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilterBefore(new JWTAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
四、示例
a. 基于用户名密码认证,返回JWT
下面是一个基于用户名密码认证,返回JWT的例子。
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody UserCredentials credentials) throws AuthenticationException {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUsername(),
credentials.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String token = Jwts.builder()
.setSubject(credentials.getUsername())
.setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, JWT_SECRET.getBytes())
.compact();
return ResponseEntity.ok(new JwtResponse(token));
}
b. 基于JWT认证,保护REST API接口
下面是一个基于JWT认证,保护REST API接口的例子。
@GetMapping("/hello")
public String hello(HttpServletRequest request) {
String header = request.getHeader("Authorization");
String token = header.replace("Bearer ", "");
Jws<Claims> jws = Jwts.parser().setSigningKey(JWT_SECRET.getBytes()).parseClaimsJws(token);
String username = jws.getBody().getSubject();
return "Hello " + username + "!";
}
以上就是关于“Springboot集成Spring Security实现JWT认证的步骤详解”的完整攻略,希望可以帮助到你。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springboot集成Spring Security实现JWT认证的步骤详解 - Python技术站