当前位置: 首页 > 编程笔记 >

SpringBoot整合SpringSecurity前后端分离实现接口登录

万俟鸿波
2023-05-05

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

今天给大家分享SpringBoot整合SpringSecurity前后端分离实现接口登录:

在前后端分离项目中,通常是通过json格式数据传递信息,但是SpingSecurity中默认获取登录账号密码方式为通过表单提交的key/value形式过去,具体官方源码处理方式如下:

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


但是如果要处理json数据进行登录,我们可以重写UsernamePasswordAuthenticationFilter类中attemptAuthentication方法实现

创建自定义过滤器LoginAuthenticationFilter

public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
   
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
   
        if (!request.getMethod().equals("POST")) {
   
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }
        //如果是application/json类型,做如下处理
        if(request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)||request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){
   
            //以json形式处理数据
            String username = null;
            String password = null;
            try {
   
            	//将请求中的数据转为map
                Map<String,String> map = new ObjectMapper().readValue(request.getInputStream(), Map.class);
                username = map.get("username");
                password = map.get("password");
            } catch (IOException e) {
   
                e.printStackTrace();
            }
            if (username == null) {
   
                username = "";
            }
            if (password == null) {
   
                password = "";
            }
            username = username.trim();
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                    username, password);
            // Allow subclasses to set the "details" property
            setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
        //否则使用官方默认处理方式
        return super.attemptAuthentication(request, response);
    }}


编写SpringSecurity配置类

@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {
   
  	@Bean
    LoginAuthenticationFilter loginAuthenticationFilter() throws Exception {
   
        LoginAuthenticationFilter filter = new LoginAuthenticationFilter();
        filter.setFilterProcessesUrl("/doLogin");
        filter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() {
   
            @Override
            public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
   
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                Hr hr = (Hr) authentication.getPrincipal();
                hr.setPassword(null);
                RespResult result = RespResult.ok("登录成功", hr);
                String msg = new ObjectMapper().writeValueAsString(result);
                writer.write(msg);
                writer.flush();
                writer.close();
            }
        });
        filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {
   
            @Override
            public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
   
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                RespResult result = RespResult.error("登录失败");;
                if (e instanceof BadCredentialsException) {
   
                    result.setMsg("用户名或密码错误,请检查");
                }else if(e instanceof LockedException){
   
                    result.setMsg("账户被锁定,请联系管理员");
                }else if(e instanceof CredentialsExpiredException){
   
                    result.setMsg("密码已过期,请联系管理员");
                }else if(e instanceof AccountExpiredException){
   
                    result.setMsg("账户已过期,请联系管理员");
                }else if(e instanceof DisabledException){
   
                    result.setMsg("账户被禁用,请联系管理员");
                }
                String msg = new ObjectMapper().writeValueAsString(result);
                writer.write(msg);
                writer.flush();
                writer.close();
            }
        });
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .logoutSuccessHandler(new LogoutSuccessHandler() {
   
                    @Override
                    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
   
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter writer = resp.getWriter();
                        RespResult result = RespResult.ok("注销退出成功");
                        String msg = new ObjectMapper().writeValueAsString(result);
                        writer.write(msg);
                        writer.flush();
                        writer.close();
                    }
                })
                .permitAll()
                .and()
                .csrf().disable();
        http.addFilterAt(loginAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
    }}


测试

成功

 类似资料:
  • 本文向大家介绍SpringBoot 配合 SpringSecurity 实现自动登录功能的代码,包括了SpringBoot 配合 SpringSecurity 实现自动登录功能的代码的使用技巧和注意事项,需要的朋友参考一下 自动登录是我们在软件开发时一个非常常见的功能,例如我们登录 QQ 邮箱: 很多网站我们在登录的时候都会看到类似的选项,毕竟总让用户输入用户名密码是一件很麻烦的事。 自动登录功能

  • 本文向大家介绍VUE+node(express)实现前后端分离,包括了VUE+node(express)实现前后端分离的使用技巧和注意事项,需要的朋友参考一下 vue作为前端的框架,node(express)作为后端的框架。无数据库,使用端口保存数据。 VUE: 使用vue-cli构建vue项目(vueapp)。 axios:(与ajax相似) axios没安装的记得装一下。(安装不细说) nod

  • 前后端分离 在B/S架构的环境中,前后端分离一直都众说纷纭,没有一个标准。我觉得打开可以分为三个阶段: 传统的分离方法 传统意义上的前后端分离,前端指的是美工、切图、设计,后端是实现代码、数据库相关的实现。美工设计和生成的前端页面,给到程序员来做集成。那么这里其实就不分什么前后端了,程序员从数据库一直搞到前端页面的样式,就是“全能型运动员“。当然,一般传统上的开发协作模式有两种: 一种是前端先写一

  • 本文向大家介绍SpringBoot整合Shiro实现登录认证的方法,包括了SpringBoot整合Shiro实现登录认证的方法的使用技巧和注意事项,需要的朋友参考一下 安全无处不在,趁着放假读了一下 Shiro 文档,并记录一下 Shiro 整合 Spring Boot 在数据库中根据角色控制访问权限 简介 Apache Shiro是一个功能强大、灵活的,开源的安全框架。它可以干净利落地处理身份验

  • 1.导入jar包 web.xml spring-security.xml

  • 本文向大家介绍SpringBoot中整合knife4j接口文档的实践,包括了SpringBoot中整合knife4j接口文档的实践的使用技巧和注意事项,需要的朋友参考一下 在项目开发中,web项目的前后端分离开发,APP开发,需要由前后端工程师共同定义接口,编写接口文档,之后大家都根据这个接口文档进行开发,到项目结束前都要一直维护 接口文档使得项目开发过程中前后端工程师有一个统一的文件进行沟通交流

  • 本文向大家介绍SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题的解决方法,包括了SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题的解决方法的使用技巧和注意事项,需要的朋友参考一下 当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异。笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想

  • 本文向大家介绍SpringBoot整合mybatis结合pageHelper插件实现分页,包括了SpringBoot整合mybatis结合pageHelper插件实现分页的使用技巧和注意事项,需要的朋友参考一下 SpringBoot整合mybatis分页操作 SpringBoot整合Mybatis进行分页操作,这里需要使用Mybatis的分页插件:pageHelper, 关于pageHelper的