Spring Security实现前后端分离Login登录功能,返回JSON提示,核心代码不到100行!

#前后端分离登录设计思路和流程图

  • 前后端分离是企业级应用开发的主流,登录功能同样采用前后端分离模式。
  • 用户信息存在数据库中。 
  • Spring Security提供身份认证。
  • 前后端交互通过JSON进行。
  • 登录成功不是页面跳转,而是一段JSON提示。

Spring Security实现前后端分离Login登录功能,返回JSON提示,核心代码不到100行!_第1张图片  

#第一步:前期准备工作

项目架构:

  • 开发环境Spring-boot 2.5.5
  • Maven
  • 数据库MySQL8.0+,存放用户、角色、用户角色对照表
  • 持久层Mybatis

数据库及表设计;MAVEN依赖;application.properties配置; 用户/角色实体类、持久层、用户服务类参考我的上一篇文章,这里不再重复讲述。

https://blog.csdn.net/m0_59562547/article/details/120864233

#第二步:WebSecurityJsonConfig核心配置类

  1. 首先注入UserService用于userDetailsService用户身份认证(包含密码、角色、锁定等)。
  2. 再配置用户登录密码需要BCryptPasswordEncoder密文认证。
  3. 再配置自定义登录参数loginid和passwd。
  4. successHandler为成功登陆后操作内容。这里我们获取当前登录用户主体信息principal,设置返回编码格式,将resp状态设置为200,将登录用户信息装入返回内容,并使用springboot自带的Jackson的objectMapper.writeValueAsString()方法将内容转化为JSON格式。
  5. failureHandler为登录失败后操作内容。这里我们设置返回编码格式,将resp状态设置为401,并根据exception类型输出返回内容,并转化为JSON格式。
  6. 最后我们设置所有接口不需要认证可访问,再关闭csrf。
package com.example.springsecurity.Config;
import com.example.springsecurity.Service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class WebSecurityJsonConfig extends WebSecurityConfigurerAdapter {
    //注入用户服务
    @Autowired
    UserService userService;
    //配置用户登录密码需要BCryptPasswordEncoder密文认证
    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder(10);
    }
    //基于数据库的用户账号密码、角色、过期、锁定等认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(userService);
    }
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception{
        httpSecurity.authorizeRequests()
                .and()
                //开启表单登录,登录URL为/login
                .formLogin()
                .loginProcessingUrl("/login")
                //自定义登录参数用户名loginid密码passwd
                .usernameParameter("loginid")
                .passwordParameter("passwd")
                //身份认证成功,采用lambda写法,传入req,resp,auth参数
                .successHandler((request, response, authentication) -> {
                    //获取当前登录用户主体信息,包括用户名密码,角色,账号状态
                    Object principal = authentication.getPrincipal();
                    //设置返回编码格式,使用PrintWriter方法输出
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    //设置resp返回状态,成功为200
                    response.setStatus(200);
                    Map map =new HashMap<>();
                    //设置返回内容
                    map.put("status",200);
                    map.put("msg",principal);
                    //使用springboot自带的Jackson转化并输出JSON信息
                    ObjectMapper objectMapper=new ObjectMapper();
                    out.write(objectMapper.writeValueAsString(map));
                    out.flush();
                    out.close();
                })
                //身份认证失败,采用lambda写法,传入req,resp,exception参数
                .failureHandler((request, response, exception) -> {
                    //设置返回编码格式,使用PrintWriter方法输出
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    //设置resp返回状态,失败为401
                    response.setStatus(401);
                    Map map = new HashMap<>();
                    map.put("status",401);
                    //根据错误状态设置返回内容
                    if(exception instanceof LockedException){
                        map.put("msg","账户被锁定,登陆失败!");
                    }else if (exception instanceof BadCredentialsException){
                        map.put("msg","账户名或者密码输入错误,登录失败!");
                    }else if (exception instanceof DisabledException){
                        map.put("msg","账户被禁用,登陆失败!");
                    }else if(exception instanceof AccountExpiredException){
                        map.put("msg","账户已过期,登陆失败!");
                    }else if(exception instanceof CredentialsExpiredException){
                        map.put("msg","密码已过期,登陆失败!");
                    }else {
                        map.put("msg","登陆失败!");
                    }
                    //使用springboot自带的Jackson转化并输出JSON信息
                    ObjectMapper objectMapper =new ObjectMapper();
                    out.write(objectMapper.writeValueAsString(map));
                    out.flush();
                    out.close();
                })
                //接口不需要认证可以访问
                .permitAll()
                .and()
                //关闭csrf
                .csrf()
                .disable();
    }
}

#第三步:启动项目开始测试 

启动MySQL数据库和Spring-boot项目,使用POSTMAN进行测试,登录请求的用户名参数是loginid,密码是passwd,使用POST请求,登录成功后返回用户的基本信息(JSON格式)。

请求网址为http://localhost:8080/login?loginid=admin&passwd=007007,效果如下图:

Spring Security实现前后端分离Login登录功能,返回JSON提示,核心代码不到100行!_第2张图片

密码错误,效果如下图:

Spring Security实现前后端分离Login登录功能,返回JSON提示,核心代码不到100行!_第3张图片 

你可能感兴趣的:(Spring-boot,spring,json,java,后端,mybatis)