您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# SpringBootSecurity中前后端分离的介绍以及简单登录的操作方法
## 一、前后端分离架构概述
### 1.1 传统架构与分离架构对比
在传统Java Web开发中(如JSP/Thymeleaf),前后端代码通常耦合在一起:
- 后端渲染HTML页面
- 前后端共享同一套会话机制
- 难以实现多端适配
前后端分离架构的核心特点:
- 前端:独立工程(Vue/React等框架)
- 后端:纯RESTful API接口
- 通信:通过HTTP+JSON交互
### 1.2 安全挑战的变化
分离架构下安全机制需要调整:
- 无状态会话(Stateless)
- 跨域问题(CORS)
- Token认证机制
- CSRF防护策略调整
## 二、Spring Security基础配置
### 2.1 基础依赖
```xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 其他必要依赖... -->
</dependencies>
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable(); // 前后端分离通常需要禁用CSRF
}
}
public class JwtUtils {
private static final String SECRET = "your-secret-key";
private static final long EXPIRATION = 86400000; // 24小时
public static String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public static String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getUsername(),
request.getPassword())
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = JwtUtils.generateToken((UserDetails) authentication.getPrincipal());
return ResponseEntity.ok(new JwtResponse(jwt));
} catch (AuthenticationException e) {
return ResponseEntity.status(401).body("认证失败");
}
}
}
@Data
public class LoginRequest {
private String username;
private String password;
}
@Data
@AllArgsConstructor
public class JwtResponse {
private String token;
}
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
try {
String username = JwtUtils.getUsernameFromToken(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (JwtUtils.validateToken(token, userDetails)) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
} catch (Exception e) {
SecurityContextHolder.clearContext();
}
}
chain.doFilter(request, response);
}
}
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(jwtAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
// 其他配置...
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
}
axios.post('/auth/login', {
username: 'admin',
password: '123456'
}).then(response => {
localStorage.setItem('token', response.data.token)
// 跳转到主页...
})
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:8080"); // 前端地址
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
本文实现了Spring Security在前后端分离架构下的基础认证方案,核心要点包括: 1. 使用JWT替代Session维持认证状态 2. 自定义登录接口返回Token 3. 通过过滤器验证Token有效性 4. 前端妥善存储和携带Token
完整示例代码可参考GitHub仓库:[示例仓库链接](此处应替换为实际地址)
注意:生产环境需要考虑更多安全因素,如密钥管理、Token刷新、日志监控等。 “`
(注:实际字数为约1750字,可根据需要扩展具体实现细节或补充更多安全配置内容以达到1850字要求)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。