Spring Security自定义登录验证及登录返回结果

  • 一.功能描述
  • 二.处理逻辑
    • 简单流程
    • 自定义UserDetails
    • 自定义UserDetailsDAO
    • 自定义UserDetailsService
    • 自定义用户登录验证逻辑AuthenticationProvider
  • 三.Spring Security基本配置信息
  • 四.登录登出自定义处理器
    • 登录成功处理器LocalAuthenticationSuccessHandler
    • 登录失败处理器LocalAuthenticationFailureHandler
    • 登出成功处理器LocalLogoutSuccessHandler
    • 匿名用户访问无权限处理器LocalAuthenticationEntryPoint
    • 认证用户访问无权限处理器LocalAccessDeniedHandler
    • 旧用户被踢处理器LocalSessionInformationExpiredStrategy

一.功能描述

使用Spring Boot + Spring Security实现自定义登录验证及登录登出返回结果.
适用于前后端分离开发的项目.如有不妥之处, 请各位大神指教.

二.处理逻辑

简单流程

验证成功
验证失败
Request登录
Spring Security
自定义LocalAuthenticationProvider
自定义LocalAuthenticationSuccessHandler
自定义LocalAuthenticationFailureHandler
验证成功
Request登出
Spring Security
自定义LocalLogoutSuccessHandler

自定义UserDetails

@javax.persistence.Entity
@org.hibernate.annotations.Table(appliesTo = "local_user_details")
public class LocalUserDetails implements java.io.Serializable, UserDetails {private static final long serialVersionUID = 1594783117560L;@javax.persistence.Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "[id]", nullable = false, unique = true, length = 0, precision = 20, scale = 0, columnDefinition = "bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键'")@ApiModelProperty(value = "主键", required = false, hidden = false, example = "主键")@JsonInclude(value = JsonInclude.Include.NON_EMPTY)private Long id;@NonNull@Size(min = 3, max = 18)@Column(name = "[userid]", nullable = false, unique = false, length = 64, precision = 0, scale = 0, columnDefinition = "varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户索引'")@ApiModelProperty(value = "用户索引", required = true, hidden = false, example = "用户索引")@JsonInclude(value = JsonInclude.Include.NON_EMPTY)private String userid = "";@NonNull@Size(min = 3, max = 64)@Column(name = "[passwd]", nullable = false, unique = false, length = 128, precision = 0, scale = 0, columnDefinition = "varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '用户密码'")@ApiModelProperty(value = "用户密码", required = true, hidden = false, example = "用户密码")@JsonInclude(value = JsonInclude.Include.NON_EMPTY)private String passwd = "";public LocalUserDetails() {}public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}public String getUserid() {return this.userid;}public void setUserid(String userid) {this.userid = userid;}public String getPasswd() {return this.passwd;}public void setPasswd(String passwd) {this.passwd = passwd;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {//返回分配给用户的角色列表return new ArrayList<>();}@Overridepublic String getPassword() {return this.getPasswd();}@Overridepublic String getUsername() {return this.getUserid();}@Overridepublic boolean isAccountNonExpired() {// 指定账户是否未过期.return true;}@Overridepublic boolean isAccountNonLocked() {// 指定账户是否未锁定.return true;}@Overridepublic boolean isCredentialsNonExpired() {// 指定密码是否未过期.return true;}@Overridepublic boolean isEnabled() {// 指定用户是否已启用, 禁用的用户无法进行身份验证.return true;}
}

自定义UserDetailsDAO

public interface LocalUserDetailsDAO extends JpaRepository<LocalUserDetails, Long>, JpaSpecificationExecutor<LocalUserDetails> {Optional<LocalUserDetails> findByUserid(String userid);
}

自定义UserDetailsService

@Service
@Transactional
public class AuthorityUserLoginInfoService implements UserDetailsService {@Autowiredprivate LocalUserDetailsDAO dao;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {Optional<LocalUserDetails> user = dao.findByUserid(username);if (user.isPresent()) {if (!user.get().isEnabled()) { throw new DisabledException("暂无权限!"); }} else {throw new UsernameNotFoundException("用户名或密码不正确!");}return user.get();}
}

自定义用户登录验证逻辑AuthenticationProvider

@Component
public class LocalAuthenticationProvider implements AuthenticationProvider {@Autowiredprivate AuthorityUserLoginInfoService userService;private final PasswordEncoder encoder = new BCryptPasswordEncoder();/** 自定义验证方式 */@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {String username = authentication.getName();String password = (String) authentication.getCredentials();// 获取Request, 获取其他参数信息ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();HttpSession session = attributes.getRequest().getSession();Object others = session.getAttribute("others");UserDetails node = userService.loadUserByUsername(username);if (!encoder.matches(password, node.getPassword())) { throw new BadCredentialsException("用户名或密码不正确!"); }return new UsernamePasswordAuthenticationToken(node, password, node.getAuthorities());}@Overridepublic boolean supports(Class<?> authentication) {return true;}
}

三.Spring Security基本配置信息

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Value(value = "${ignoringAntMatchers:/**}")private String ignoringAntMatchers;@Value(value = "${loginPage:/login}")private String loginPage;@Value(value = "${loginProcessingUrl:/api/user/login}")private String loginProcessingUrl;@Value(value = "${logoutUrl:/api/user/logout}")private String logoutUrl;@Value(value = "${expiredUrl:/login}")private String expiredUrl;@Autowiredprivate DataSource dataSource;@Autowiredprivate AuthorityUserLoginInfoService userService;@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(4);}@Beanpublic AuthenticationProvider authenticationProvider() {return new LocalAuthenticationProvider();}@Overridepublic void configure(AuthenticationManagerBuilder auth) throws Exception {// 自定义用户登录验证auth.authenticationProvider(authenticationProvider());// 指定密码加密所使用的加密器为passwordEncoder(), 需要将密码加密后写入数据库auth.userDetailsService(this.userService).passwordEncoder(passwordEncoder());// 不删除凭据,以便记住用户auth.eraseCredentials(false);}@Overridepublic void configure(WebSecurity web) throws Exception {// 设置不拦截规则web.ignoring().antMatchers(this.ignoringAntMatchers.split(","));}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 设置拦截规则http.authorizeRequests().anyRequest().authenticated();// 自定义登录信息http.csrf().disable().formLogin() //.loginPage(this.loginPage) // 自定义登录页url,默认为/login.loginProcessingUrl(this.loginProcessingUrl) // 登录验证地址, 即RequestMapping地址// 用户名的请求字段. 默认为org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY.usernameParameter("username")// 用户名的请求字段. 默认为org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY.passwordParameter("password") // .successHandler(new LocalAuthenticationSuccessHandler()) // 登录验证成功后, 执行的内容// .defaultSuccessUrl("/index") // 登录验证成功后, 跳转的页面, 如果自定义返回内容, 请使用successHandler方法// .successForwardUrl("/index") // 登录验证成功后, 跳转的页面, 如果自定义返回内容, 请使用successHandler方法.failureHandler(new LocalAuthenticationFailureHandler()) // 登录验证失败后, 执行的内容// .failureUrl("/login?error")  // 登录验证失败后, 跳转的页面, 如果自定义返回内容, 请使用failureHandler方法.permitAll();// 自定义异常处理器http.exceptionHandling() // 异常处理器// 用来解决匿名用户访问无权限资源时的异常.authenticationEntryPoint(new LocalAuthenticationEntryPoint())// 用来解决认证过的用户访问无权限资源时的异常, 跳转的页面, 如果自定义返回内容, 请使用accessDeniedHandler方法// .accessDeniedPage("/error")// 用来解决认证过的用户访问无权限资源时的异常.accessDeniedHandler(new LocalAccessDeniedHandler());// 自定义注销信息http.logout() // .logoutUrl(this.logoutUrl) // 登出验证地址, 即RequestMapping地址.logoutSuccessHandler(new LocalLogoutSuccessHandler()) // 登录验证成功后, 执行的内容// .logoutSuccessUrl("/login?logout") // 登录验证成功后, 跳转的页面, 如果自定义返回内容, 请使用logoutSuccessHandler方法.deleteCookies("JSESSIONID") // 退出登录后需要删除的cookies名称.invalidateHttpSession(true) // 退出登录后, 会话失效.permitAll();// remember-me配置http.rememberMe() // // org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer.DEFAULT_REMEMBER_ME_NAME.rememberMeCookieName("remember-me")// org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer.DEFAULT_REMEMBER_ME_NAME.rememberMeParameter("remember-me")// org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.TWO_WEEKS_S.tokenValiditySeconds(360000)// tokenRepository.tokenRepository(new LocalPersistentTokenRepository(this.dataSource));// session管理http.sessionManagement().sessionFixation().changeSessionId() //.maximumSessions(1) // 最大会话数.maxSessionsPreventsLogin(false) // 达到最大数后, 强制验证, 踢出旧用户// 旧用户被踢出后, 跳转的页面, 如果自定义返回内容, 请使用expiredSessionStrategy方法// .expiredUrl("/login?expired")// 旧用户被踢出后, 执行的内容.expiredSessionStrategy(new LocalSessionInformationExpiredStrategy());}@Bean@Overrideprotected AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}}

四.登录登出自定义处理器

登录成功处理器LocalAuthenticationSuccessHandler

public class LocalAuthenticationSuccessHandler implements AuthenticationSuccessHandler {private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException, ServletException {response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().print(gson.toJson(new Result<>(ResultStatus.SUCCESS_LOGIN)));}
}

登录失败处理器LocalAuthenticationFailureHandler

public class LocalAuthenticationFailureHandler implements AuthenticationFailureHandler {private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)throws IOException, ServletException {response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().print(gson.toJson(new Result<>(ResultStatus.ERROR_LOGIN)));}
}

登出成功处理器LocalLogoutSuccessHandler

public class LocalLogoutSuccessHandler implements LogoutSuccessHandler {private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException, ServletException {response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().print(gson.toJson(new Result<>(20001, "登出成功!")));}
}

匿名用户访问无权限处理器LocalAuthenticationEntryPoint

public class LocalAuthenticationEntryPoint implements AuthenticationEntryPoint {private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)throws IOException, ServletException {response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().print(gson.toJson(new Result<>(ResultStatus.WRONG_DEAL)));}
}

认证用户访问无权限处理器LocalAccessDeniedHandler

public class LocalAccessDeniedHandler implements AccessDeniedHandler {private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)throws IOException, ServletException {response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().print(gson.toJson(new Result<>(ResultStatus.WRONG_DEAL)));}
}

旧用户被踢处理器LocalSessionInformationExpiredStrategy

public class LocalSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();@Overridepublic void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {HttpServletResponse response = event.getResponse();response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().print(gson.toJson(new Result<>(20002, "用户已退出!")));}
}

Spring Security自定义登录验证及登录返回结果相关推荐

  1. spring security 自定义认证登录

    spring security 自定义认证登录 1.概要 1.1.简介 spring security是一种基于 Spring AOP 和 Servlet 过滤器的安全框架,以此来管理权限认证等. 1 ...

  2. (二)Spring Security自定义登录成功或失败处理器

    目录 一:创建登录成功处理器 二:创建登录失败处理器 三:添加处理器 三. 项目地址 我们接着上一章 Spring Security最简单的搭建,进行开发 LoginSuccessHandler 和L ...

  3. java授权失败_自定义Spring Security的身份验证失败处理方法

    1.概述 在本快速教程中,我们将演示如何在Spring Boot应用程序中自定义Spring Security的身份验证失败处理.目标是使用表单登录方法对用户进行身份验证. 2.认证和授权(Authe ...

  4. 基于Spring Security与JWT实现单点登录

    基于RBAC的权限管理 RBAC(Role-Based Access Control):基于角色的访问控制 当前项目中,RBAC具体的表现为: 管理员表:ams_admin 角色表:ams_role ...

  5. 手把手教你如何使用Spring Security(上):登录授权

    文章目录 一.什么是 Spring Security? 官方介绍 通俗来讲 二.初始搭建 创建 启动 三.项目原理 原理 思考 四.登录认证 登录过滤器 配置过滤器链 类补充 五.登录效果 效果演示 ...

  6. Spring Security——自定义认证错误提示信息及自适应返回格式解决方案

    解决方案 package com.hailiu.web.handler;import com.hailiu.model.Log; import com.hailiu.web.bean.Response ...

  7. Spring Boot + Spring Security + JWT + 微信小程序登录

    Spring Boot + Spring Security + JWT + 微信小程序登录整合教程 参考文章 文章目录 整合思想 整合步骤 1. AuthenticationToken 2. Auth ...

  8. 基于Spring Security的AJAX请求需要登录的解决方案

    基于Spring Security的AJAX请求需要登录的解决方案 参考文章: (1)基于Spring Security的AJAX请求需要登录的解决方案 (2)https://www.cnblogs. ...

  9. Spring Security 自定义资源服务器实践

    相关文章: OAuth2的定义和运行流程 Spring Security OAuth实现Gitee快捷登录 Spring Security OAuth实现GitHub快捷登录 Spring Secur ...

最新文章

  1. D - Fliptile POJ - 3279(翻转问题)
  2. python判断数据类型
  3. AutoLayout(自动布局)详细教程
  4. vc6.0垃圾文件清理工具_MacClean360 for Mac(mac系统清理软件)
  5. Visual studio内存泄露检查工具--BoundsChecker
  6. mysql修改字段 新增字段
  7. 梯度直方图(HOG,Histogram of Gradient)
  8. java 蓝桥杯算法训练 s01串(题解)
  9. 实体经济不改变经营思路和销售模式
  10. Ubuntu ROS Kinect2安装
  11. 第一次面试且失败的经历
  12. SheetJS 读取excel文件转出json
  13. 单文件小型数据库的选择
  14. java多线程编程实例
  15. 三泰串口卡linux驱动,工业多串口卡.pdf
  16. oracle sql 的语句
  17. LeetCode 2248、多个数组求交集
  18. 计算机对无人机的影响,无人机中的人工智能和自主性你了解多少
  19. Intent传递数据的方法
  20. C++ Point类求两点距离

热门文章

  1. [Unity3D]Unity3D游戏开发之跑酷游戏项目讲解
  2. python stdout_python stdout 什么用
  3. 史上最全面的Buffalo WHR-G300N CH v2 刷OpenWrt教程
  4. 源“ySQL 8.0 Community Server”的GPG密钥已安装,但是不适用于此软件包。请检查源的公钥URL是否配置正确。
  5. 家里电脑怎么连接公司电脑啊 这可愁坏我了
  6. 股权转让个人所得税要交多少
  7. 社保+年假查询指南 -- 小黑日常超细详解
  8. RocketMQ源码级别面试题板块
  9. 程序员送给女朋友的3D旋转相册附背景音乐
  10. 云技术在android平台上的应用程序,安卓系统上的ERP云应用