Spring Security + OAuth2
第一章 Spring Security 快速入门
第二章 Spring Security 自定义配置
第三章 Spring Security 前后端分离配置
第四章 Spring Security 身份认证
第五章 Spring Security 授权
第六章 OAuth2
文章目录
1、用户认证流程
登录成功后调用AuthenticationSuccessHandler
登录失败后调用AuthenticationFailureHandler
前后端分离时,前端发送请求给后端,后端需要返回一个json数据给前端。springSecurity是如何做到的呢?
- SpringSecurity 通过UsernamePasswordAuthenticationFilter获取前端输入的用户名和密码
- 根据用户名和密码生成UsernamePasswordAuthenticationToken
- AuthenticationManager会判断Token是否正确,根据结果发给相应的handler
- 此时handler返回json数据给前端。
2、引入fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
3、认证成功的响应
3.1、成功结果处理
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
Object principal = authentication.getPrincipal(); //获取用户身份信息
//获取用户凭证信息。
//Object credentials = authentication.getCredentials();
//获取用户权限信息。
//Collection<? extends GrantedAuthority> authenticationAuthorities = authentication.getAuthorities();
HashMap result = new HashMap<>();
result.put("code",0);
result.put("messsage","登录成功");
result.put("data",principal);
//将结果对象转换成json字符串。
String json = JSON.toJSONString(result);
//返回json数据到前端。
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}
3.2、配置MyAuthenticationSuccessHandler
@Configuration //配置类
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// authorizeHttpRequests() 开启授权保护
// anyRequest() 对所以请求开启授权保护
// authenticated()已认证请求会自动授权。
http.authorizeHttpRequests(
authorize -> authorize
//对所有请求就随时
.anyRequest()
.authenticated()
);
http.formLogin(form -> {
form
.loginPage("/login")
.permitAll() //无需授权即可访问。
.usernameParameter("myName")//配置自定义的表单用户名参数
.passwordParameter("myPassword")//配置自定义的表单密码参数
.failureUrl("/login?failure")
.successHandler(new MyAuthenticationSuccessHandler())//认证成功时的处理。
;
});
//关闭csrf攻击防御
http.csrf(csrf->csrf.disable());
return http.build();
}
}
4、认证失败响应
4.1、失败结果处理
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String msg = exception.getLocalizedMessage();
HashMap result = new HashMap<>();
result.put("code",-1);//失败
result.put("messsage",msg);
//将结果对象转换成json字符串。
String json = JSON.toJSONString(result);
//返回json数据到前端。
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}
4.2、配置MyAuthenticationFailureHandler
@Configuration //配置类
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// authorizeHttpRequests() 开启授权保护
// anyRequest() 对所以请求开启授权保护
// authenticated()已认证请求会自动授权。
http.authorizeHttpRequests(
authorize -> authorize
//对所有请求就随时
.anyRequest()
.authenticated()
);
http.formLogin(form -> {
form
.loginPage("/login")
.permitAll() //无需授权即可访问。
.usernameParameter("myName")//配置自定义的表单用户名参数
.passwordParameter("myPassword")//配置自定义的表单密码参数
.failureUrl("/login?failure")
.successHandler(new MyAuthenticationSuccessHandler())//认证成功时的处理。
.failureHandler(new MyAuthenticationFailureHandler())//认证失败时的处理。
;
});//表单授权方式
// .httpBasic(withDefaults());//基本授权方式
//关闭csrf攻击防御
http.csrf(csrf->csrf.disable());
return http.build();
}
}
5、注销响应
5.1、注销结果处理
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
HashMap result = new HashMap<>();
result.put("code",0);//失败
result.put("messsage","注销成功");
//将结果对象转换成json字符串。
String json = JSON.toJSONString(result);
//返回json数据到前端。
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}
5.2、SecurityFilterChain 配置
在WebSecurityConfig,加入注销配置。
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// authorizeHttpRequests() 开启授权保护
// anyRequest() 对所以请求开启授权保护
// authenticated()已认证请求会自动授权。
http.authorizeHttpRequests(
authorize -> authorize
//对所有请求就随时
.anyRequest()
.authenticated()
);
http.formLogin(form -> {
form
.loginPage("/login")
.permitAll() //无需授权即可访问。
.usernameParameter("myName")//配置自定义的表单用户名参数
.passwordParameter("myPassword")//配置自定义的表单密码参数
.failureUrl("/login?failure")
.successHandler(new MyAuthenticationSuccessHandler())//认证成功时的处理。
.failureHandler(new MyAuthenticationFailureHandler())//认证失败时的处理。
;
});//表单授权方式
// .httpBasic(withDefaults());//基本授权方式
//注销配置
http.logout(logout->{
logout.logoutSuccessHandler(new MyLogoutSuccessHandler());//注销成功时的处理
});
//关闭csrf攻击防御
http.csrf(csrf->csrf.disable());
return http.build();
}
6、请求未认证的接口
6.1、实现AuthenticationEntryPoint接口
Servlert Authentication Architecture :: Spring Security
当访问一个需要认证之后才能访问的接口的时候,Spring Security会使用 AuthenticationEntryPoint 将用户请求跳转到登录页面,要求用户提供登录凭证。
这里我们也希望系统返回json结果,因此我们定义类实现AuthenticationEntryPoint接口
package com.security.demo.config;
import ...
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint{
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
String localizeMessage = "需要登录";
HashMap result = new HashMap();
result.put("code",-1);
result.put("message",localizeMessage);
//将结果对象转换成json字符串
String json = JSON.toJSONString(result);
//返回json数据到前端
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}
6.2、配置MyAuthenticationFailureHandler
//注销配置
http.logout(logout->{
logout.logoutSuccessHandler(new MyLogoutSuccessHandler());//注销成功时的处理
});
7、跨域
跨域全称是跨域资源共享(Cross-Origin Resources Sharing,CORS),它是浏览器的保护机制,只允许网页请求统一域名下的服务,同一域名指=>协议,域名,端口号都要保持一致,如果有一项不同,那么就是跨域请求,在前后端分离的项目中,需要解决跨域的问题。
在SpringSecurity中解决跨域很简单,在配置文件中添加如下配置即可
//跨域
http.cors(withDefaults());