Spring Security--前后端json交互

 successHandler 

 onAuthenticationSuccess里的第一个参数是当前请求对象,第二个是响应对象,第三个是验证成功的用户信息

小技巧:ALT+enter生成lambda表达式

 我们准备一个ResBean

package org.ikun.security_demo.model;

public class ResBean {
    private Integer status;
    private String msg;
    private Object data;


    public static ResBean ok(String msg,Object data){
        return new ResBean(200,msg,data);
    }
    public static ResBean ok(String msg){
        return new ResBean(200,msg,null);
    }

    public static ResBean error(String msg,Object data){
        return new ResBean(204,msg,data);
    }
    public static ResBean error(String msg){
        return new ResBean(204,msg,null);
    }
    private ResBean(){

    }

    private ResBean(Integer status, String msg, Object data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

Security里的代码

package org.ikun.security_demo;


import com.fasterxml.jackson.databind.ObjectMapper;
import org.ikun.security_demo.model.ResBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //开始认证
        //设置登录,注销,表单登录不用拦截,其他请求要拦截
        http.authorizeRequests().antMatchers("/","/login.html").anonymous()
                //所有的请求,类似于shiro中的 /**
                .anyRequest()
                //必须要认证之后才能访问,类似于shiro的authc
                .authenticated()
                .and()
                //开始配置登录表单
                .formLogin()
                //配置登录页面,如果访问了一个需要登录以后才能访问的页面,那么就会自动登录到这个页面
                .loginPage("/login.html")
                //配置处理登录请求的接口,其实就是配置了过滤器里的拦截规则,将来的登录请求就会在过滤器中被处理
                .loginProcessingUrl("/doLogin")
                //配置登录表单中用户名的 key
                .usernameParameter("username")
                //配置登录表单中的密码 默认也是username 和 password
                .passwordParameter("password")
                //配置登录成功后访问的接口
               // .defaultSuccessUrl("/hello")
                //登录失败后访问的接口
                //.failureUrl("/login.html")
                //登录成功处理器
                .successHandler((request, response, authentication) -> {
                    response.setContentType("application/json;charset=utf-8");
                    ResBean resBean = ResBean.ok("登陆成功", authentication.getPrincipal());//getPrincipal()就是你的用户对象
                    String s = new ObjectMapper().writeValueAsString(resBean);
                    response.getWriter().write(s);
                })
                //关闭默认的csrf认证
                .and().csrf().disable();

    }
    
}

登陆成功后,返回结果如下

 登录失败的回调亦然。failureHandler

package org.ikun.security_demo;


import com.fasterxml.jackson.databind.ObjectMapper;
import org.ikun.security_demo.model.ResBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //开始认证
        //设置登录,注销,表单登录不用拦截,其他请求要拦截
        http.authorizeRequests().antMatchers("/","/login.html").anonymous()
                //所有的请求,类似于shiro中的 /**
                .anyRequest()
                //必须要认证之后才能访问,类似于shiro的authc
                .authenticated()
                .and()
                //开始配置登录表单
                .formLogin()
                //配置登录页面,如果访问了一个需要登录以后才能访问的页面,那么就会自动登录到这个页面
                .loginPage("/login.html")
                //配置处理登录请求的接口,其实就是配置了过滤器里的拦截规则,将来的登录请求就会在过滤器中被处理
                .loginProcessingUrl("/doLogin")
                //配置登录表单中用户名的 key
                .usernameParameter("username")
                //配置登录表单中的密码 默认也是username 和 password
                .passwordParameter("password")
                //配置登录成功后访问的接口
               // .defaultSuccessUrl("/hello")
                //登录失败后访问的接口
                //.failureUrl("/login.html")
                //登录成功处理器
                .successHandler((request, response, authentication) -> {
                    response.setContentType("application/json;charset=utf-8");
                    ResBean resBean = ResBean.ok("登陆成功", authentication.getPrincipal());//getPrincipal()就是你的用户对象
                    String s = new ObjectMapper().writeValueAsString(resBean);
                    response.getWriter().write(s);
                })
                .failureHandler((request, response, exception) -> {
                    //登录失败可能有很多种原因

                    response.setContentType("application/json;charset=utf-8");
                    ResBean resBean = ResBean.ok("登陆失败");
                    if (exception instanceof BadCredentialsException){
                        resBean.setMsg("用户名或密码输入错误,登录失败");
                    }else if (exception instanceof UsernameNotFoundException){
                        //这个异常默认隐藏了,所以这个分支不会进来,怕有人试密码
                    }else if (exception instanceof LockedException){
                        resBean.setMsg("账户被锁定,登录失败");
                    }else if (exception instanceof AccountExpiredException){
                        resBean.setMsg("账户过期,登录失败");
                    }else if (exception instanceof CredentialsExpiredException){
                        resBean.setMsg("密码过期,登录失败");
                    }else if (exception instanceof DisabledException){
                        resBean.setMsg("账户被禁用,登录失败");
                    }
                    String s = new ObjectMapper().writeValueAsString(resBean);
                    response.getWriter().write(s);
                })
                //关闭默认的csrf认证
                .and().csrf().disable();

    }

}

我们看一下效果

 ok没问题

最后介绍一个exceptionHandling

用户未登录就访问某一个页面,就会触发这个方法
.exceptionHandling()
                //用户未登录就访问某一个页面,就会触发这个方法
                .authenticationEntryPoint((request, response, authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    ResBean resBean = ResBean.error("尚未登录,请登录");
                    String s = new ObjectMapper().writeValueAsString(resBean);
                    response.getWriter().write(s);
                })

效果如下:

猜你喜欢

转载自blog.csdn.net/a2285786446/article/details/131129591