springboot实现jwt
时间: 2023-09-30 19:06:23 浏览: 126
SpringBoot整合JWT
在Spring Boot中实现JWT(Json Web Token)认证可以通过添加依赖项和编写配置类来实现。以下是一些基本步骤:
1. 添加依赖项
在pom.xml文件中添加以下依赖项:
```xml
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
```
2. 编写配置类
编写一个配置类,用于创建JWT Token并验证请求。以下是一个示例配置类:
```java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.crypto.SecretKey;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Key;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.token-prefix}")
private String tokenPrefix;
@Value("${jwt.header-string}")
private String headerString;
@Value("${jwt.expiration-time}")
private long expirationTime;
private UserDetailsService userDetailsService;
public SecurityConfig(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@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("/api/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecretKey secretKey() {
return Keys.hmacShaKeyFor(secret.getBytes());
}
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
private class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
String username = request.getParameter("username");
String password = request.getParameter("password");
return authenticationManager().authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token = createJwt(authResult);
response.addHeader(headerString, tokenPrefix + token);
}
private String createJwt(Authentication auth) {
Claims claims = Jwts.claims().setSubject(auth.getName());
claims.put("roles", auth.getAuthorities());
Key key = secretKey();
return Jwts.builder()
.setClaims(claims)
.signWith(key, SignatureAlgorithm.HS256)
.setExpiration(new Date(System.currentTimeMillis() + expirationTime))
.compact();
}
}
}
```
在上面的示例中,我们定义了一个JwtAuthenticationFilter,它是一个Spring Boot过滤器,用于从请求中提取用户名和密码,然后创建一个JWT令牌并将其添加到响应头中。我们还定义了一个createJwt方法,该方法使用JJWT库构建JWT令牌。
3. 配置应用程序属性
在application.properties文件中,配置应用程序属性:
```properties
jwt.secret=your-secret-key
jwt.token-prefix=Bearer
jwt.header-string=Authorization
jwt.expiration-time=86400000
```
在上面的示例中,我们定义了以下属性:
- jwt.secret:用于签署JWT的密钥。
- jwt.token-prefix:JWT令牌的前缀,在这里我们使用“Bearer”。
- jwt.header-string:JWT令牌将添加到请求头的属性名称。
- jwt.expiration-time:JWT令牌的过期时间,以毫秒为单位。
4. 编写控制器
编写一个控制器,该控制器用于处理用户身份验证请求。以下是一个示例控制器:
```java
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AuthController {
private AuthenticationManager authenticationManager;
private UserDetailsService userDetailsService;
private PasswordEncoder passwordEncoder;
public AuthController(AuthenticationManager authenticationManager, UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
this.authenticationManager = authenticationManager;
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
}
@PostMapping("/api/authenticate")
public ResponseEntity<?> authenticate(@RequestBody AuthRequest request) {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());
String token = createJwt(authentication);
return ResponseEntity.ok(new AuthResponse(token));
}
private String createJwt(Authentication auth) {
String username = auth.getName();
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + expirationTime))
.signWith(secretKey(), SignatureAlgorithm.HS256)
.compact();
}
}
```
在上面的示例中,我们定义了一个authenticate方法,该方法使用Spring Boot的AuthenticationManager进行身份验证,并返回JWT令牌。
5. 运行应用程序并测试
现在,您可以构建并运行应用程序,并使用Postman或curl发送POST请求到/authenticate端点,以获取JWT令牌,如下所示:
```
POST /api/authenticate
{
"username": "user",
"password": "password"
}
```
成功身份验证后,您将收到一个包含JWT令牌的响应,如下所示:
```
HTTP/1.1 200 OK
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDA2MjJ9.5OQJtjXt7nG6TcIvYK3Z_6LnfzRf0xX6ZVhVlQ6qfYs
```
您可以将此JWT令牌添加到请求头中,以使用Spring Boot保护的任何其他端点。
阅读全文