一、Spring Security认证 & 授权(前后端分离)
1.1、MyWebSecurityConfigurerAdapter7002
/**
* @Author : 一叶浮萍归大海
* @Date: 2024/1/11 21:50
* @Description: Spring Security配置类
*/
@Configuration
public class MyWebSecurityConfigurerAdapter7002 extends WebSecurityConfigurerAdapter {
@Resource
private MyAuthenticationSuccessHandler7002 successHandler;
@Resource
private MyAuthenticationFailureHandler7002 failureHandler;
@Resource
private MyLogoutSuccessHandler logoutSuccessHandler;
@Resource
private MyAuthenticationEntryPoint authenticationEntryPoint;
/**
* 密码加密器
* @return
*/
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
/**
* 配置基于内存的用户
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("123456")
.roles("admin")
.and()
.withUser("root")
.password("123456")
.roles("root");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/helloWorld")
.permitAll()
.anyRequest()
.authenticated()
.and()
/**
* 登录成功 & 登录失败回调
*/
.formLogin()
.loginPage("/login")
.successHandler(successHandler)
.failureHandler(failureHandler)
.and()
/**
* 注销登录回调
*/
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(logoutSuccessHandler)
.permitAll()
.and()
.csrf()
.disable()
/**
* 未认证回调
*/
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint);
}
}
1.2、MyAuthenticationSuccessHandler7002
/**
* @Author : 一叶浮萍归大海
* @Date: 2024/1/12 09:55
* @Description: 认证(登录)成功处理器
*/
@Component
public class MyAuthenticationSuccessHandler7002 implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
R r = R.ok().data(authentication.getPrincipal());
out.write(new ObjectMapper().writeValueAsString(r));
out.flush();
out.close();
}
}
1.3、MyAuthenticationFailureHandler7002
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/1/12 10:05
* @Description: 认证(登录)失败处理器
*/
@Component
public class MyAuthenticationFailureHandler7002 implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
R r = R.error();
if (exception instanceof LockedException) {
r.data(SpringSecurityConstants.LOCKED_ERROR_MESSAGE);
} else if (exception instanceof CredentialsExpiredException) {
r.data(SpringSecurityConstants.CREDENTIALS_EXPIRED_ERROR_MESSAGE);
} else if (exception instanceof AccountExpiredException) {
r.data(SpringSecurityConstants.ACCOUNT_EXPIRED_ERROR_MESSAGE);
} else if (exception instanceof DisabledException) {
r.data(SpringSecurityConstants.DISABLED_ERROR_MESSAGE);
} else if (exception instanceof BadCredentialsException) {
r.data(SpringSecurityConstants.BAD_CREDENTIALS_ERROR_MESSAGE);
} else if (exception instanceof AuthenticationServiceException) {
r.data(SpringSecurityConstants.VERIFY_CODE_ERROR_MESSAGE);
} else {
r.data(SpringSecurityConstants.LOGIN_ERROR_COMMON_MESSAGE);
}
out.write(new ObjectMapper().writeValueAsString(r));
out.flush();
out.close();
}
}
1.4、MyLogoutSuccessHandler7002
/**
* @Author : 一叶浮萍归大海
* @Date: 2024/01/12 11:26
* @Description: 注销登录处理器
*/
@Component
public class MyLogoutSuccessHandler7002 implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
R r = R.ok().data(SpringSecurityConstants.LOGOUT_SUCCESS_MESSAGE);
out.write(new ObjectMapper().writeValueAsString(r));
out.flush();
out.close();
}
}
1.5、MyAuthenticationEntryPoint7002
/**
* @Author : 一叶浮萍归大海
* @Date: 2024/01/12 11:27
* @Description: 未认证处理方案(用户未登录就访问资源)
*/
@Component
public class MyAuthenticationEntryPoint7002 implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
R r = R.error(ResponseEnum.HTTP_UNAUTHORIZED_ERROR.getCode(),ResponseEnum.HTTP_UNAUTHORIZED_ERROR.getMessage());
out.write(new ObjectMapper().writeValueAsString(r));
out.flush();
out.close();
}
}
1.6、SpringSecurityConstants7002
/**
* @Author 一叶浮萍归大海
* @Description Spring Security认证 & 授权常量类
* @Date 2024/01/12 10:06
*/
public class SpringSecurityConstants {
public static final String LOGOUT_SUCCESS_MESSAGE = "注销成功!";
public static final String LOCKED_ERROR_MESSAGE = "账户被锁定,请联系管理员!";
public static final String CREDENTIALS_EXPIRED_ERROR_MESSAGE = "密码过期,请联系管理员!";
public static final String ACCOUNT_EXPIRED_ERROR_MESSAGE = "账户过期,请联系管理员!";
public static final String DISABLED_ERROR_MESSAGE = "账户被禁用,请联系管理员!";
public static final String BAD_CREDENTIALS_ERROR_MESSAGE = "用户名或者密码错误,请重新输入!";
public static final String VERIFY_CODE_ERROR_MESSAGE = "验证码错误!";
public static final String LOGIN_ERROR_COMMON_MESSAGE = "登录失败,请联系管理员!";
}
1.7、R
/**
* @Author 一叶浮萍归大海
* @Description
* @Date 2023/01/12 10:06
*/
@Data
public class R<T> {
private Integer code;
private String message;
private T data;
/**
* 构造函数私有化
*/
private R(){}
/**
* 返回成功结果
* @return
*/
public static R ok(){
R r = new R();
r.setCode(ResponseEnum.SUCCESS.getCode());
r.setMessage(ResponseEnum.SUCCESS.getMessage());
return r;
}
/**
* 返回失败结果
* @return
*/
public static R error(){
R r = new R();
r.setCode(ResponseEnum.ERROR.getCode());
r.setMessage(ResponseEnum.ERROR.getMessage());
return r;
}
public static R error(int code, String msg) {
R r = new R();
r.setCode(code);
r.setMessage(msg);
return r;
}
/**
* 设置特定的结果
* @param responseEnum
* @return
*/
public static R setResult(ResponseEnum responseEnum){
R r = new R();
r.setCode(responseEnum.getCode());
r.setMessage(responseEnum.getMessage());
return r;
}
public R data(T entity) {
this.setData(entity);
return this;
}
/**
* 设置特定的响应消息
* @param message
* @return
*/
public R message(String message){
this.setMessage(message);
return this;
}
/**
* 设置特定的响应码
* @param code
* @return
*/
public R code(Integer code){
this.setCode(code);
return this;
}
}
1.8、ResponseEnum
/**
* @Author 一叶浮萍归大海
* @Description
* @Date 2023/5/30 15:55
*/
@Getter
@ToString
@AllArgsConstructor
public enum ResponseEnum {
/**
* 响应状态码 & 响应信息映射
*/
SUCCESS(200, "成功!"),
ERROR(201, "失败!"),
SERVER_INTERNAL_ERROR(500, "服务器内部错误,请联系管理员!"),
PARAMETER_VALIDATE_FAILED_ERROR(10001, "参数校验失败,请联系管理员!"),
BUSINESS_ERROR(10002, "业务异常,请联系管理员"),
// =================== Spring Cloud Alibaba Sentinel统一异常处理 ===================
SENTINEL_FLOW_EXCEPTION(20001,"接口被限流,请联系管理员!"),
SENTINEL_DEGRADE_EXCEPTION(20002,"接口被降级,请联系管理员!"),
SENTINEL_PARAM_FLOW_EXCEPTION(20003,"热点参数限流,请联系管理员!"),
SENTINEL_SYSTEM_BLOCK_EXCEPTION(20004,"触发系统保护规则,请联系管理员!"),
SENTINEL_AUTHORITY_EXCEPTION(20005,"授权规则不通过,请联系管理员!"),
// =================== Spring Security统一异常处理 ===================
HTTP_UNAUTHORIZED_ERROR(401, "尚未登录,请登录!"),
HTTP_FORBIDDEN_ERROR(403, "权限不足,请联系管理员!"),
;
/**
* 响应状态码
*/
private Integer code;
/**
* 响应信息
*/
private String message;
}