小明:嘿,小李,我最近在研究统一身份认证平台,感觉挺复杂的,你能帮我解释一下吗?
小李:当然可以!统一身份认证平台(Identity Authentication Platform)就是用来集中管理用户身份信息、权限以及访问控制的系统。它通常用于企业级应用中,确保不同系统之间能够安全地共享用户数据。
小明:那它是怎么工作的呢?有没有什么具体的实现方式?
小李:最常见的方式是使用OAuth 2.0协议或者JWT(JSON Web Token)。OAuth 2.0是一种授权框架,允许第三方应用在不暴露用户密码的情况下获取资源访问权限;而JWT则是一种轻量级的令牌格式,常用于无状态的身份验证。
小明:听起来不错,那我们可以用Spring Boot来做一个简单的演示吗?
小李:当然可以!我们可以用Spring Boot搭建一个简单的统一身份认证平台,然后做一个登录和访问受保护资源的演示。
小明:好啊,那我们先从搭建项目开始吧。
小李:首先,我们需要创建一个Spring Boot项目,可以选择Web、Security、OAuth2等依赖。
小明:那具体的代码怎么写呢?能不能给我看看示例?
小李:好的,下面是一个简单的Spring Boot项目结构,我们先创建一个基础的控制器和配置类。
小明:那这个项目需要哪些依赖?
小李:我们在pom.xml文件中添加以下依赖:

小明:这些依赖的作用是什么?
小李:web模块用于构建REST API;security模块用于处理认证和授权;oauth2-client用于集成OAuth 2.0客户端功能。
小明:那接下来我们怎么配置认证服务呢?
小李:我们可以创建一个配置类,定义认证规则和登录页面。
小明:能给我看一下代码吗?
小李:好的,下面是配置类的代码:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
return http.build();
}
}
小明:这个配置是做什么的?
小李:这段代码启用了基于表单的登录,任何请求都需要经过认证,登录页面是“/login”,并且允许所有人访问登录页面。
小明:那我们怎么创建登录页面呢?
小李:我们可以创建一个简单的HTML页面放在resources/templates目录下,例如login.html。
小明:那这个页面应该包含什么内容?
小李:一个简单的表单,提交到/login路径,包含用户名和密码字段。
小明:那我们可以再创建一个控制器来处理登录请求吗?
小李:是的,我们可以创建一个HomeController,处理根路径和登录页面。
小明:那具体的代码是怎样的?
小李:以下是 HomeController 的代码:
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
@GetMapping("/login")
public String login() {
return "login";
}
}
小明:那我们怎么测试这个登录功能呢?
小李:我们可以启动项目,然后访问 http://localhost:8080,会跳转到登录页面。输入用户名和密码后,就可以进入主页了。
小明:那如果我们要实现更高级的认证功能,比如使用JWT呢?
小李:JWT 是一种无状态的认证方式,适合分布式系统。我们可以使用 Spring Security 和 JWT 结合起来实现。
小明:那具体怎么做呢?
小李:首先,我们需要生成 JWT 令牌,然后在请求头中携带它进行认证。
小明:那我们可以写一个生成令牌的工具类吗?
小李:是的,下面是一个简单的 JWT 工具类:
public class JwtUtil {
private static final String SECRET_KEY = "your-secret-key";
private static final long EXPIRATION = 86400000; // 1 day in milliseconds
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public static String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
小明:那我们怎么在Spring Security中使用这个JWT呢?
小李:我们可以创建一个自定义的过滤器,检查每个请求中的JWT令牌,并将其转换为认证对象。
小明:那具体的代码是怎样的?
小李:下面是JWT过滤器的代码:
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
try {
String username = JwtUtil.getUsernameFromToken(token);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (JwtException e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
return;
}
}
filterChain.doFilter(request, response);
}
}
小明:那我们怎么把这个过滤器加到Spring Security中呢?
小李:我们可以修改之前的SecurityConfig类,添加这个过滤器。
小明:那代码是怎样的?
小李:下面是更新后的SecurityConfig类:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().authenticated();
return http.build();
}
}
小明:这样是不是就实现了基于JWT的认证?
小李:是的,现在每次请求都必须带上Authorization头,格式为Bearer + JWT令牌。
小明:那我们怎么测试这个功能呢?
小李:我们可以编写一个简单的控制器,返回受保护的资源。
小明:那代码是怎样的?
小李:下面是受保护资源的控制器:
@RestController
public class ProtectedResourceController {
@GetMapping("/protected")
public String getProtectedData() {
return "This is a protected resource!";
}
}
小明:那我们怎么生成JWT令牌呢?
小李:我们可以创建一个登录接口,返回JWT令牌。
小明:那代码是怎样的?
小李:下面是登录接口的代码:
@RestController
public class AuthController {
@PostMapping("/login")
public ResponseEntity
// 这里应验证用户名和密码
String token = JwtUtil.generateToken("user");
return ResponseEntity.ok("Bearer " + token);
}
}
小明:这样我们就完成了一个简单的统一身份认证平台的演示。
小李:是的,这只是一个基础版本,实际生产环境中还需要考虑更多安全措施,如令牌刷新、黑名单、加密等。
小明:谢谢你,小李,我现在对统一身份认证平台有了更深的理解。
小李:不客气!如果你有兴趣,我们还可以进一步扩展这个项目,比如集成OAuth 2.0或使用数据库存储用户信息。
小明:太好了,我期待下一步的学习!
