security自定义json格式登录

spring security默认的登录提交方式是表单提交,为formdata格式,记录如何使用json格式提交登录

1. 自定义jsonLoginFilter

security实现登录时,会调用 UsernamePasswordAuthenticationFilter,下面的部分源码,查看源码可以看出,其中attemptAuthentication方法是实现表单提交的,我们可以重写这个方法,使其实现json格式提交。

public UsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
    }

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {
            String username = this.obtainUsername(request);
            username = username != null ? username.trim() : "";
            String password = this.obtainPassword(request);
            password = password != null ? password : "";
            UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
            this.setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    }

我们创建一个JsonLoginFilter类继承UsernamePasswordAuthenticationFilter

import cn.edu.huuc.mdcs.pojo.SysAccount;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;

/**
 * 自定义json格式登录的过滤器(security默认登录提交为表单提交)
 * @author spring
 * @date 2024/5/15 10:07
 */
public class JsonLoginFilter extends UsernamePasswordAuthenticationFilter {

    public JsonLoginFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if(!request.getMethod().equals("POST")){
            throw new AuthenticationServiceException("Authentication method not supported" + request.getMethod());
        }
        String contentType = request.getContentType();
        //说明是以json的形式传递参数
        if (MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType)) {
            if (!request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            }
            String username = null;
            String password = null;
            try {
                SysAccount user = new ObjectMapper().readValue(request.getInputStream(), SysAccount.class);
                username = user.getUsername();
                username = (username != null) ? username.trim() : "";
                password = user.getPassword();
                password = (password != null) ? password : "";
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
            setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
        return super.attemptAuthentication(request, response);
    }

}

实际上,我在源码上只添加了

if (MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType))

来判断是否为json格式传输的

这里提醒一下:

1.MediaType.APPLICATION_JSON_UTF8_VALUE已被弃用,使用      MediaType.APPLICATION_JSON_VALUE即可

2.不要在类上添加@Component注解

2. 配置SecurityConfig

首先需要添加一个Bean,来配置登录的信息

    @Bean
    public JsonLoginFilter jsonLoginFilter(AuthenticationManager authenticationManager) {
        JsonLoginFilter jsonLoginFilter = new JsonLoginFilter(authenticationManager);
        jsonLoginFilter.setFilterProcessesUrl("/api/login");
        jsonLoginFilter.setUsernameParameter("accountName");
        jsonLoginFilter.setPasswordParameter("accountPassword");
        jsonLoginFilter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
        jsonLoginFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
        return jsonLoginFilter;
    }

其中myAuthenticationSuccessHandler,myAuthenticationFailureHandler为验证成功失败走的类,需要自己定义

然后再SecurityFilterChain配置

这里我没有展示其他的配置,仅仅针对jsonLoginFilter的配置做了配置

 @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, 
                              JsonLoginFilter jsonLoginFilter)throws Exception {
        return httpSecurity
                    .addFilterAt(jsonLoginFilter, UsernamePasswordAuthenticationFilter.class)
                    .build();
 }

下面的代码是之前默认配置的formLogin,就可以删除了

                .formLogin((formLogin) -> {
                    formLogin.loginProcessingUrl(Constants.LOGIN_URI)//登录处理地址,不需要写controller
                            .usernameParameter("accountName")
                            .passwordParameter("accountPassword")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);
                })

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值