融合门户
张伟(开发者):李娜,我们最近在做融合服务门户的开发,需要把招标文件的功能也整合进去。你对登录模块有什么建议吗?
李娜(架构师):张伟,首先得确定用户身份验证的方式。比如,是使用传统的用户名密码,还是OAuth、JWT等现代方式?这会影响后续的接口设计和安全性。
张伟:目前公司内部系统用的是基于Token的认证,可能更适合我们现在的架构。不过,招标文件可能需要更严格的权限控制。
李娜:没错,我们可以考虑引入RBAC(基于角色的访问控制)。这样不同的用户角色可以访问不同级别的招标文件。比如,普通用户只能查看公开的招标信息,而管理员可以编辑或下载完整文件。
张伟:那登录流程应该怎么设计呢?我之前做过一个简单的登录页面,但没考虑到多系统集成的问题。
李娜:登录应该是一个独立的服务模块,最好是微服务架构中的一个子系统。这样其他模块如招标文件系统就可以通过API调用登录服务来验证用户身份。
张伟:明白了,那具体怎么实现呢?有没有示例代码可以参考?
李娜:当然有。下面是一个简单的登录接口示例,使用Spring Boot框架,结合JWT实现身份验证。
// LoginController.java
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private UserService userService;
@PostMapping("/login")
public ResponseEntity> login(@RequestBody LoginRequest request) {
User user = userService.findByUsername(request.getUsername());
if (user == null || !user.getPassword().equals(request.getPassword())) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
}
String token = JwtUtil.generateToken(user.getUsername());
return ResponseEntity.ok(new AuthResponse(token));
}
}
张伟:这个代码看起来不错,但我还想看看前端是怎么处理登录的。
李娜:前端可以用Axios发送POST请求到登录接口,获取返回的token,并将其存储在localStorage或者sessionStorage中。之后每次请求都需要带上这个token作为Authorization头。
张伟:明白了,那在访问招标文件的时候,怎么确保用户已经登录了呢?
李娜:我们需要在每个需要鉴权的接口上添加拦截器。比如,在Spring中可以使用Filter或者AOP来检查请求头中的token是否有效。
张伟:那具体的拦截逻辑怎么写呢?能给我一个例子吗?
李娜:好的,下面是一个简单的JWT拦截器示例。
// JwtInterceptor.java
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtil jwtUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
if (jwtUtil.validateToken(token)) {
String username = jwtUtil.getUsernameFromToken(token);
request.setAttribute("username", username);
return true;
}
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
return false;
}
}
张伟:这个拦截器很实用,那在招标文件的控制器里,怎么根据用户角色来限制访问呢?
李娜:可以使用Spring Security的注解,比如@PreAuthorize,根据用户角色来决定是否允许访问某个方法。
张伟:比如,如果用户是“admin”,可以访问所有文件;如果是“viewer”,只能查看公开的文件。
李娜:对,下面是一个示例。
// BidFileController.java
@RestController
@RequestMapping("/api/bidfiles")
public class BidFileController {
@GetMapping("/{id}")
@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
public ResponseEntity getBidFile(@PathVariable Long id) {
BidFile file = bidFileService.findById(id);
return ResponseEntity.ok(file);
}
@PostMapping
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity createBidFile(@RequestBody BidFile file) {
BidFile saved = bidFileService.save(file);
return ResponseEntity.ok(saved);
}
}
张伟:这样就能实现权限控制了。不过,如果用户没有登录,直接访问招标文件页面会怎么样?
李娜:这时候拦截器就会阻止请求,返回401错误。前端可以根据这个错误跳转到登录页面,或者提示用户未登录。
张伟:明白了。那登录系统的安全性方面需要注意什么?
李娜:首先,密码不能明文传输,必须加密。其次,JWT的签名要足够强,避免被篡改。另外,token的有效期也要合理设置,防止长期有效带来的安全风险。
张伟:那是不是还需要考虑跨域问题?比如,前端和后端部署在不同的域名下?
李娜:是的,跨域请求需要配置CORS。在Spring Boot中,可以通过添加@EnableWebMvc和配置WebMvcConfigurer来解决这个问题。
张伟:有没有示例代码?
李娜:有的,下面是配置CORS的代码。
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("Content-Type", "Authorization");
}
}
张伟:看来我们的登录系统已经初步成型了。接下来是不是要考虑测试和部署?
李娜:是的,测试是关键。可以使用JUnit进行单元测试,Postman测试API。部署的话,可以考虑Docker容器化,方便管理和扩展。

张伟:好的,谢谢你的指导!
李娜:不客气,有问题随时找我!