spring boo t整合security 前后端分离
时间: 2023-10-10 09:07:58 浏览: 118
Spring Boot与Spring Security可以很好地用于前后端分离的项目中,包括前端使用React、Vue等框架,后端使用Spring Boot作为RESTful API的提供者。
以下是一个简单的示例,演示如何使用Spring Boot和Spring Security进行前后端分离:
1. 前端请求API
在前端中,您可以使用Axios或Fetch等工具来向后端发送请求。例如,以下代码演示了如何使用Axios发送POST请求:
```
axios.post('/api/login', {
username: 'user',
password: 'password'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
```
2. 后端配置
在后端中,您需要配置Spring Security以允许跨域请求和基于令牌的身份验证。以下是一个简单的配置示例:
```
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.cors()
.and()
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("password"))
.roles("USER");
}
}
```
该配置允许所有来源的跨域请求,并要求所有/api/**请求都需要进行身份验证。在身份验证过程中,使用JWT令牌进行身份验证。
3. JWT过滤器
在上面的配置中,我们使用了JwtAuthenticationFilter和JwtAuthorizationFilter两个过滤器来处理JWT令牌的身份验证和授权。这些过滤器需要根据您的实际需求进行修改,以下是一个简单的示例:
```
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(), creds.getPassword()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token = Jwts.builder()
.setSubject(((User) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET)
.compact();
response.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);
}
}
```
```
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String header = request.getHeader(SecurityConstants.HEADER_STRING);
if (header == null || !header.startsWith(SecurityConstants.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(SecurityConstants.HEADER_STRING);
if (token != null) {
String user = Jwts.parser()
.setSigningKey(SecurityConstants.SECRET)
.parseClaimsJws(token.replace(SecurityConstants.TOKEN_PREFIX, ""))
.getBody()
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
```
4. 登录API
最后,您需要编写一个登录API,该API允许用户通过POST请求进行身份验证,并返回JWT令牌。以下是一个简单的示例:
```
@RestController
@RequestMapping("/api")
public class AuthController {
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody UserCredentials credentials) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String token = Jwts.builder()
.setSubject(authentication.getName())
.setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET)
.compact();
return ResponseEntity.ok()
.header(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token)
.build();
}
}
```
这个简单的示例演示了如何在Spring Boot和Spring Security中进行前后端分离,并使用JWT令牌进行身份验证。您可以根据自己的需求进行修改和扩展。
阅读全文