「这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战」
确保Web应用程序的安全是一个固有的复杂命题。Spring Security为Java开发者提供了一个强大的框架来满足这一需求,但这一强大的工具伴随着一个陡峭的学习曲线。
本文简要介绍了用Spring Security保护REST API背后的基本组件。我们将建立一个简单的应用,使用JSON Web Token(JWT)来存储用户的信息。
JWT由于其简单性和紧凑性,正在迅速成为持有授权信息的标准方法。
具有简单登录能力的前端
Spring Web默认会在resources/static文件夹中提供文件。这就是客户端以一个小的index.html文件形式存在的地方。这将使你了解到JavaScript前端是如何与服务器安全互动的。
这个简单的index.html文件允许用户点击一个按钮,看到从受保护的端点返回的信息。它还提供了一个简单的登录功能。你可以在清单1中看到处理这些交互的JS。
清单 1.受保护的API和登录调用(index.html)。
<script>
let token = null;
async function protectedAPI(){
let headers = {};
if (token) headers["Authorization"] = "Bearer " + token;
let response = await fetch("/protected", {
headers
});
let text = await response.text();
if (response.ok){
document.getElementById("protectedMessage").innerHTML = text;
} else {
document.getElementById("protectedMessage").innerHTML = "You must log in first";
}
}
async function login(){
let response = await fetch("/open/login", {
method: 'post',
body:
JSON.stringify({username:document.getElementById("username").value,password:document.getElementById("password").value}),
headers: {
"Content-Type": "application/json"
}
});
if (response.ok){
let text = await response.text();
token = text;
document.getElementById("login-msg").innerHTML = "Login success";
} else {
document.getElementById("login-msg").innerHTML = "Failed to login: " + response.status;
}
}
</script>
复制代码
清单1依赖于两个API端点。/open/login和/protected。它使用登录调用的结果来设置token变量的值,如果token存在,受保护的调用会在授权头中发送token。当用户访问安全端点时,服务器将使用该token来验证用户的授权。
受保护的端点MyController.java
MyController是一个简单明了的Spring Web REST映射,如清单2所示。`
清单2.MyController.java
@GetMapping({ "/protected" })
public String protectedEndpoint() {
return "Protected Endpoint Response";
}
复制代码
请注意,在映射的路由级别上没有安全布线存在。
SecurityConfig.java
SecurityConfig.java文件是安全设置的中心。让我们从这里开始并向外移动。
该类用@configuration和@EnableWebSecurity做了注解,提醒Spring注意安全问题已经激活,该类将对其应用设置。
大部分的工作是在列表4中看到的configure()方法中完成的。
清单3.SecurityConfig.configure()
private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
new AntPathRequestMatcher("/"), new AntPathRequestMatcher("/open/**")
);
TokenAuthenticationProvider provider;
private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);
protected void configure(final HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(STATELESS)
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
.and()
.authenticationProvider(provider)
.addFilterBefore(restAuthenticationFilter(), AnonymousAuthenticationFilter.class)
.authorizeRequests()
.requestMatchers(PROTECTED_URLS)
.authenticated()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.logout().disable();
}
TokenAuthenticationFilter restAuthenticationFilter() throws Exception {
final TokenAuthenticationFilter filter = new TokenAuthenticationFilter(PROTECTED_URLS);
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationSuccessHandler(successHandler());
return filter;
}
复制代码
对清单3的一些评论。配置方法使用Ant模式匹配器(PROTECTED_URLS)来允许对静态目录("/")和("/open/")路径之后的任何请求通过,而不需要进行认证检查。这意味着你仍然可以点击/static/index.html文件,而登录端点可以托管在/open/login。
请注意,该配置还添加了提供者,即TokenAuthenticationProvider,以及过滤器,由TokenAuthenticationFilter处理。注意过滤器在AnonymousAuthenticationFilter之前,它是Spring Security的一部分。
感谢观看,如果您有兴趣,可以关注一下我,方便查看后续文章,一起学习,共同进步,不胜感激!




近期评论