FastAPI token认证踩坑----swagger 接口测试没有token

FastAPI的SwaggerUI在API调用中authorization:Bearer undefined

错误原因:

是我自定义了返回的数据结构,没有access_token,token_type这两个关键字

解决办法:

FastAPI的SwaggerUI在API调用中包含您的令牌,请确保您的/token端点在响应中包含2个必需的关键字。

access_token:这应该是您的令牌值

token_type:此值应为 Bearer

所以您的返回应该是这样的,

{
    access_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9',
    token_type: 'Bearer'
}

如果您返回的结构中如下定义或者其他的返回结构,没有包含access_token,token_type

{
    token: 'abcdefg12345token'
}

任何SwaggerUI API调用都只会显示undefined

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用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有效,接口将返回相应的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪荡的三木先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值