springboot token登录认证接口
时间: 2023-09-04 10:12:04 浏览: 141
可以使用Spring Security来实现Token认证。以下是一个简单的示例:
1. 添加依赖
在pom.xml文件中添加以下依赖:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
```
2. 配置Spring Security
在Spring Boot的配置类中,添加以下配置:
```java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll().
anyRequest().authenticated().and().
exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/security",
"/swagger-ui.html", "/webjars/**", "/api-docs/**");
}
}
```
其中,`MyUserDetailsService`是一个自定义的`UserDetailsService`实现,用于获取用户信息;`JwtRequestFilter`是一个自定义的过滤器,用于解析和验证Token。
3. 实现认证接口
创建一个`AuthenticationController`类,实现登录认证接口:
```java
@RestController
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private MyUserDetailsService userDetailsService;
@PostMapping("/authenticate")
public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()));
} catch (BadCredentialsException e) {
throw new Exception("Incorrect username or password", e);
}
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(token));
}
}
```
其中,`AuthenticationRequest`是一个包含用户名和密码的DTO对象;`AuthenticationResponse`是一个包含Token的DTO对象。
4. 实现自定义UserDetailsService
创建一个`MyUserDetailsService`类,实现`UserDetailsService`接口,用于获取用户信息。这里假设用户信息存储在数据库中。
```java
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
new ArrayList<>());
}
}
```
5. 实现自定义JwtTokenUtil
创建一个`JwtTokenUtil`类,用于生成和解析Token。这里使用了`io.jsonwebtoken`库来实现。
```java
@Component
public class JwtTokenUtil {
private static final String SECRET_KEY = "secret";
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
long now = System.currentTimeMillis();
long validity = now + 3600000;
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(now))
.setExpiration(new Date(validity))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
private boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
private Date getExpirationDateFromToken(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration();
}
public String getUsernameFromToken(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();
}
}
```
其中,`SECRET_KEY`是用于签名的密钥。
6. 实现自定义JwtRequestFilter
创建一个`JwtRequestFilter`类,继承`OncePerRequestFilter`,用于解析和验证Token。
```java
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.getUsernameFromToken(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
```
7. 测试接口
使用Postman等工具,向`/authenticate`接口发送POST请求,请求体中包含用户名和密码,如:
```json
{
"username": "test",
"password": "test"
}
```
如果用户名和密码正确,接口将返回一个包含Token的JSON对象,如:
```json
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTYwMzQwNTQ3LCJleHAiOjE1NjAzNDQxNDd9.1x4abT-7TbBw4S7n5fFwKkqYQ8mlmW84v6vKjL_6iQI"
}
```
之后,每次请求需要认证的接口时,需要在请求头中添加`Authorization`字段,值为`Bearer <Token>`,如:
```
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTYwMzQwNTQ3LCJleHAiOjE1NjAzNDQxNDd9.1x4abT-7TbBw4S7n5fFwKkqYQ8mlmW84v6vKjL_6iQI
```
如果Token有效,接口将返回相应的数据。
阅读全文