下面我将详细讲解“Spring Security前后端分离两种实战方案”的完整攻略。
简介
Spring Security 是一款开源的认证和授权框架,可以实现对系统的安全性保护。在前后端分离的架构中,Spring Security 的实现需要特别注意。本文将从两个方面介绍 Spring Security 的前后端分离实现方案。
方案一:基于 Token 的验证方式
Token 验证方式就是先发送登录请求,登录成功后服务器返回 Token,然后客户端将 Token 保存在本地,在后续的请求中添加 Token,并在服务器端进行验证。这种方式比较常见,也是应用比较广泛的一种方式。
实现步骤如下:
-
前端登录时向后端发送登录请求(接口可以自己定义),后台验证通过后生成 Token 并返回给前端。
示例代码如下:
@PostMapping("/login")
public ResponseEntity login(@RequestBody User user) {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword())
);
} catch (Exception e) {
throw new RuntimeException("用户名或密码错误");
}
String token = jwtTokenUtil.generateToken(user.getUsername());
return ResponseEntity.ok().header("Authorization", token).build();
}
上述代码中,我们从请求参数中拿到用户名和密码,然后调用 authenticationManager.authenticate 进行验证,验证通过后,调用 jwtTokenUtil.generateToken 生成 Token 并通过 header 返回给前端。 -
前端将 Token 存储在本地,随后每次请求都在 header 中带上 Token。
示例代码如下:
axios.interceptors.request.use(config => {
const token = window.localStorage.getItem('token')
if (token) {
config.headers.Authorization = token
}
return config
}, err => Promise.reject(err))
上述代码中,我们使用 axios 发送请求,拦截器会在请求前加入 token。 -
后台需要对每个请求进行 Token 验证,验证通过后才能正常访问。
示例代码如下:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String header = request.getHeader(headerName);
if (header == null || !header.startsWith(tokenHead)) {
return;
}
String authToken = header.substring(tokenHead.length());
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username == null) {
return;
}
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
上述代码中,我们从 header 中获取 token,然后解析出 username。接着,我们通过 username 获取 user 对象,并使用 jwtTokenUtil 验证 Token 是否有效,如果有效则将 user 放入 SecurityContextHolder 中进行验证。通过以上步骤,我们就完成了 Token 验证方式的实现。
方案二:基于 OAuth2 的验证方式
OAuth2 是一款流行的授权框架,可以实现对应用程序及其资源的安全保护。
实现步骤如下:
- 在认证服务器上配置 OAuth2 客户端信息,包括客户端 ID、客户端密码、授权方式等。
在 Spring Security 中,我们可以使用@EnableAuthorizationServer
和@EnableResourceServer
注解来激活 OAuth2 的认证服务和资源服务。
示例代码如下:
```
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// ...
}
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
// ...
}
```
-
前端向认证服务器请求授权,如果授权通过则返回 access_token。
示例代码如下:
axios.post('/oauth/token', null, {
params: {
grant_type: 'password',
client_id: 'app',
client_secret: 'app_secret',
username: 'user',
password: 'user_password'
}
}).then(response => {
const { access_token } = response.data
const token_type = response.data.token_type
const Authorization = `${token_type} ${access_token}`
window.localStorage.setItem('access_token', Authorization)
axios.defaults.headers.common.Authorization = Authorization
}).catch(error => {
console.log(error)
})
上述代码中,我们使用 axios 发送请求,包含了必要的参数(client_id、client_secret、username、password)进行认证,如果认证通过则返回 access_token。 -
前端请求后端 API 时,在 header 中携带 access_token。
示例代码如下:
axios.get('/api/user', {
headers: {
Authorization: `Bearer ${token}`
}
})
上述代码中,我们在 header 中带入 access_token,让后端接口能够验证用户是否有权限访问该接口。 -
后端需要对每个请求进行 access_token 验证,验证通过后才能正常访问。
示例代码如下:
```
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.tokenStore(tokenStore).resourceId("api")
}
@Override
public void configure(HttpSecurity http) {
http.authorizeRequests()
.antMatchers("/api/**").authenticated()
.and()
.csrf().disable()
.headers().frameOptions().disable()
}
``
tokenStore
上述代码中,我们通过配置 token 的存储方式,
resourceId指定应用的资源 ID。使用
http.authorizeRequests()表示对请求进行验证,
antMatchers()指定需要验证的 URL,
.authenticated()` 表示需要验证通过才能访问这个 URL。并且禁用了 CSRF 防护和 X-Frame-Options 防护。
至此,我们就完成了基于 OAuth2 的验证方式的实现。
结论
本文通过两个不同方式(Token 和 OAuth2)介绍了 Spring Security 前后端分离的实现方案,每个方案都基于不同的验证协议。当然,每个项目都有自己特定的需求,选择不同的实现方案是有必要的。但是无论你使用哪种方案,都必须对实现方式和安全策略进行仔细评估。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Sping Security前后端分离两种实战方案 - Python技术站