系列五、Spring Security认证 & 授权(前后端分离)

发布时间:2024年01月12日

一、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;

}

文章来源:https://blog.csdn.net/HelloWorld20161112/article/details/135548395
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。