Spring Boot是一个非常流行的Java Web框架,它提供了很多便捷的功能和工具,可以帮助我们快速构建Web应用程序。其中,单点登录(Single Sign-On,简称SSO)是一个非常重要的功能,可以让用户在多个应用程序之间无需重复登录。以下是Spring Boot简单实现单点登录的示例代码的完整攻略:
- 使用Spring Security实现单点登录
Spring Security是Spring Boot中的一个重要组件,它提供了很多安全功能和工具,可以帮助我们实现单点登录。以下是一个示例:
- 创建一个Spring Boot项目,并添加Spring Security依赖。
- 创建一个名为SecurityConfig的配置类,并使用@EnableWebSecurity注解来启用Web安全功能。我们使用HttpSecurity对象来配置安全规则,并使用formLogin()方法来启用表单登录功能。
- 创建一个名为UserController的控制器类,并使用@PreAuthorize注解来限制访问控制器的权限。我们使用@PreAuthorize注解来指定只有具有ROLE_USER角色的用户才能访问控制器。
- 在application.properties文件中配置Spring Security的用户名和密码。
以下是示例代码:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER");
}
}
@RestController
public class UserController {
@GetMapping("/user")
@PreAuthorize("hasRole('USER')")
public String getUser() {
return "Hello, user!";
}
}
在上面的示例中,我们使用Spring Security来实现单点登录功能。我们创建了一个名为SecurityConfig的配置类,并使用@EnableWebSecurity注解来启用Web安全功能。我们使用HttpSecurity对象来配置安全规则,并使用formLogin()方法来启用表单登录功能。我们创建了一个名为UserController的控制器类,并使用@PreAuthorize注解来限制访问控制器的权限。我们在application.properties文件中配置了Spring Security的用户名和密码。
- 使用JWT实现单点登录
JWT(JSON Web Token)是一种轻量级的身份验证和授权机制,可以帮助我们实现单点登录。以下是一个示例:
- 创建一个Spring Boot项目,并添加Spring Security和JWT依赖。
- 创建一个名为JwtTokenUtil的工具类,用于生成和验证JWT令牌。
- 创建一个名为JwtUserDetailsService的用户服务类,用于从数据库中获取用户信息。
- 创建一个名为JwtAuthenticationEntryPoint的认证入口类,用于处理认证异常。
- 创建一个名为JwtAuthenticationTokenFilter的认证过滤器类,用于验证JWT令牌。
- 创建一个名为JwtAuthorizationTokenFilter的授权过滤器类,用于授权用户访问资源。
- 创建一个名为UserController的控制器类,并使用@PreAuthorize注解来限制访问控制器的权限。
以下是示例代码:
@Component
public class JwtTokenUtil {
private static final String SECRET = "mySecret";
private static final long EXPIRATION_TIME = 864_000_000; // 10 days
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public String getUsernameFromToken(String token) {
return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody().getSubject();
}
public boolean validateToken(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private boolean isTokenExpired(String token) {
Date expiration = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody().getExpiration();
return expiration.before(new Date());
}
}
@Service
public class JwtUserDetailsService 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<>());
}
}
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
logger.error("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
logger.error("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
logger.error("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
logger.error("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
@RestController
public class UserController {
@GetMapping("/user")
@PreAuthorize("hasRole('USER')")
public String getUser() {
return "Hello, user!";
}
}
在上面的示例中,我们使用JWT来实现单点登录功能。我们创建了一个名为JwtTokenUtil的工具类,用于生成和验证JWT令牌。我们创建了一个名为JwtUserDetailsService的用户服务类,用于从数据库中获取用户信息。我们创建了一个名为JwtAuthenticationEntryPoint的认证入口类,用于处理认证异常。我们创建了一个名为JwtAuthenticationTokenFilter的认证过滤器类,用于验证JWT令牌。我们创建了一个名为JwtAuthorizationTokenFilter的授权过滤器类,用于授权用户访问资源。我们创建了一个名为UserController的控制器类,并使用@PreAuthorize注解来限制访问控制器的权限。
以上是Spring Boot简单实现单点登录的示例代码的完整攻略,其中包括使用Spring Security实现单点登录和使用JWT实现单点登录的示例。根据应用程序的需求和开发人员的经验,可以选择最适合的方法来实现单点登录功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springboot简单实现单点登录的示例代码 - Python技术站