Swagger/OpenAPI 是一种用于描述 RESTful API 的规范,它允许开发者定义 API 的结构、参数、响应模型等信息。在实际应用中,经常需要根据用户的授权级别返回不同的模型表示,例如管理员能看到更多字段,普通用户只能看到部分字段。
在 OpenAPI 规范中,可以为不同权限级别定义不同的模型:
components:
schemas:
UserBasic:
type: object
properties:
id:
type: integer
username:
type: string
email:
type: string
UserAdmin:
allOf:
- $ref: '#/components/schemas/UserBasic'
- type: object
properties:
createdAt:
type: string
format: date-time
lastLogin:
type: string
format: date-time
isActive:
type: boolean
结合安全定义和不同响应:
paths:
/users/{id}:
get:
summary: Get user by ID
security:
- adminAuth: []
- userAuth: []
responses:
'200':
description: Successful response
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/UserAdmin'
- $ref: '#/components/schemas/UserBasic'
headers:
X-RateLimit-Limit:
schema:
type: integer
description: Request limit per hour
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<?> getUser(@PathVariable Long id,
@AuthenticationPrincipal UserDetails userDetails) {
User user = userService.findById(id);
if (hasAdminRole(userDetails)) {
return ResponseEntity.ok(toAdminDto(user));
} else {
return ResponseEntity.ok(toBasicDto(user));
}
}
private UserBasicDto toBasicDto(User user) {
UserBasicDto dto = new UserBasicDto();
dto.setId(user.getId());
dto.setUsername(user.getUsername());
dto.setEmail(user.getEmail());
return dto;
}
private UserAdminDto toAdminDto(User user) {
UserAdminDto dto = new UserAdminDto();
dto.setId(user.getId());
dto.setUsername(user.getUsername());
dto.setEmail(user.getEmail());
dto.setCreatedAt(user.getCreatedAt());
dto.setLastLogin(user.getLastLogin());
dto.setActive(user.isActive());
return dto;
}
private boolean hasAdminRole(UserDetails userDetails) {
return userDetails.getAuthorities().stream()
.anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"));
}
}
解决方案:
解决方案:
解决方案示例(使用 Spring Security Test):
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(roles = "USER")
public void getUser_asUser_returnsBasicInfo() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").exists())
.andExpect(jsonPath("$.username").exists())
.andExpect(jsonPath("$.createdAt").doesNotExist());
}
@Test
@WithMockUser(roles = "ADMIN")
public void getUser_asAdmin_returnsFullInfo() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").exists())
.andExpect(jsonPath("$.username").exists())
.andExpect(jsonPath("$.createdAt").exists());
}
}
通过合理设计 OpenAPI 规范和实现代码,可以有效地为不同授权级别提供不同的模型表示,既保证了安全性又提供了良好的开发者体验。
没有搜到相关的文章