CAS单点登录-登录校验码(十七)

2024-05-15 17:48

本文主要是介绍CAS单点登录-登录校验码(十七),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CAS单点登录-登录校验码(十七)

本章教程用的cas版本为5.1.5

简介

在一些常规的老系统不得不加入固定的验证码,当然这是为了流控、暴力破解、降低数据库压力等等原因,那么接下来会讲解一些如何进行解决这些问题


流控/防爆:

这一层可以在监控系统中做,例如同一个ip高频率访问可以进行一些禁止策略处理,除了这个当然可以加验证码了,但传统的老系统往往是一开始就添加验证码,这样给用户的感觉不太友好了,毕竟并不是每个过来的都是机器人。例如可以添加一些策略,连续三次密码错误才加验证码,验证码也可以随机,图片验证,手机验证码,扫描校验,算法验证码等等

降低数据库压力:

用户密码,用户信息可以从缓存中获取,因为用户并不是经常改密码改用户信息,当未发生改变时都可以缓存中获取密码进行匹配,若每次都从数据库中获取密码进行匹配这肯定是对数据库增加了不少压力,当然了如果增加缓存层肯定是对系统增加了复杂度,这要看技术团队如何衡量这个事情了

本章计划

  • 如何自定义Controller
  • 输出校验码
  • 登录前置验证码进行校验

温馨提示

本章不包括:自定义校验码策略,流控策略

实战

自定义控制器(校验码)

在spring mvc中用到控制器就多了,可能传统的就是加@Controller或者继承或者实现Controller的接口这样然后让spring容器能够识别扫描到即可

那么在cas中依然是这样,简单看看以下代码

AbstractDelegateController已经加了@Controller

import org.apereo.cas.web.AbstractDelegateController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;/*** 验证码控制器** @author Carl* @date 2017/10/27*/
public class CaptchaController extends AbstractDelegateController {private ICaptchaWriter<String> captchaWriter;private SessionCaptchaResultAware<String> aware;public CaptchaController(ICaptchaWriter<String> captchaWriter, SessionCaptchaResultAware<String> aware) {this.captchaWriter = captchaWriter;this.aware = aware;}public SessionCaptchaResultAware<String> getAware() {return aware;}public ICaptchaWriter<String> getCaptchaWriter() {return captchaWriter;}@Overridepublic boolean canHandle(HttpServletRequest request, HttpServletResponse response) {return true;}@GetMapping(value = CaptchaConstants.REQUEST_MAPPING, produces = "image/png")@Overrideprotected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {//设置response头信息//禁止缓存response.setHeader("Cache-Control", "no-cache");response.setContentType("image/png");OutputStream outputStream =  response.getOutputStream();//存储验证码到sessionString text = getAware().getAndStore(request.getSession());getCaptchaWriter().write(text, outputStream);return null;}
}
import com.carl.sso.support.captcha.CaptchaController;
import com.carl.sso.support.captcha.ICaptchaWriter;
import com.carl.sso.support.captcha.SessionCaptchaResultAware;
import com.carl.sso.support.captcha.SessionCaptchaResultProvider;
import com.carl.sso.support.captcha.string.StringCaptchaResultAware;/*** Cage验证码控制器** @author Carl* @date 2017/10/27*/
public class CageCaptchaController extends CaptchaController {public CageCaptchaController(ICaptchaWriter<String> captchaWriter, SessionCaptchaResultAware<String> aware) {super(captchaWriter, aware);}public CageCaptchaController() {super(new CageStringCaptchaWriter(), new StringCaptchaResultAware(new SessionCaptchaResultProvider(), new CageStringTokenGenerator()));}public CageCaptchaController(SessionCaptchaResultProvider provider) {super(new CageStringCaptchaWriter(), new StringCaptchaResultAware(provider, new CageStringTokenGenerator()));}
}

注册:

import com.carl.sso.support.captcha.SessionCaptchaResultProvider;
import com.carl.sso.support.captcha.imp.cage.CageCaptchaController;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author Carl* @date 2017/10/28* @since 1.5.0*/
@Configuration("captchaConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CaptchaConfiguration {//注册bean到spring容器@Bean@ConditionalOnMissingBean(name = "captchaController")public CageCaptchaController captchaController() {return new CageCaptchaController(captchaResultProvider());}@Beanpublic SessionCaptchaResultProvider captchaResultProvider() {return new SessionCaptchaResultProvider();}
}

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.carl.sso.support.captcha.config.CaptchaConfiguration

以上即完成一个controller的自定义,当然了,这个比较简单不是本章的重点,但上面完成了一个简单的验证码的输出

登录前置验证码进行校验

需求:提交表单后进行校验码匹配,若失败跳转回登录页,那么以下代码我们模仿了官网的谷歌验证码模块

  1. 新增action
  2. 把action设置到提交表单流程

action代码为了方便测试,以下逻辑是在demo主题下触发,并且有系统参数进来才响应

import com.carl.sso.support.auth.UsernamePasswordSysCredential;
import com.carl.sso.support.captcha.ICaptchaResultProvider;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;/*** 登录校验码** @author Carl* @date 2017/11/18*/
public class ValidateLoginCaptchaAction extends AbstractAction {private static final Logger LOGGER = LoggerFactory.getLogger(ValidateLoginCaptchaAction.class);//验证码存储器private ICaptchaResultProvider<HttpSession, String> captchaResultProvider;private static final String CODE = "captchaError";public ValidateLoginCaptchaAction(ICaptchaResultProvider<HttpSession, String> captchaResultProvider) {this.captchaResultProvider = captchaResultProvider;}/*** 前端验证码*/public static final String CODE_PARAM = "validateCode";@Overrideprotected Event doExecute(RequestContext context) throws Exception {Credential credential = WebUtils.getCredential(context);//系统信息不为空才检测校验码if(credential instanceof UsernamePasswordSysCredential && ((UsernamePasswordSysCredential) credential).getSystem() != null) {if (isEnable()) {LOGGER.debug("开始校验登录校验码");HttpServletRequest request = WebUtils.getHttpServletRequest();HttpSession httpSession = request.getSession();//校验码String inCode = request.getParameter(CODE_PARAM);//校验码失败跳转到登录页if(!this.captchaResultProvider.validate(httpSession, inCode)) {return getError(context);}}}return null;}/*** 是否开启验证码* @return*/private boolean isEnable() {return true;}/*** 跳转到错误页* @param requestContext* @return*/private Event getError(final RequestContext requestContext) {final MessageContext messageContext = requestContext.getMessageContext();messageContext.addMessage(new MessageBuilder().error().code(CODE).build());return getEventFactorySupport().event(this, CODE);}
}

注册:

@ConditionalOnMissingBean(name = "validateLoginCaptchaAction")
@Bean
@RefreshScope
public Action validateLoginCaptchaAction() {ValidateLoginCaptchaAction validateCaptchaAction = new ValidateLoginCaptchaAction(captchaResultProvider);return validateCaptchaAction;
}

流程设置:


package com.carl.sso.support.captcha.config;import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.web.flow.AbstractCasWebflowConfigurer;
import org.apereo.cas.web.flow.CasWebflowConstants;
import org.springframework.context.ApplicationContext;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.ActionState;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.ViewState;
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;import java.util.ArrayList;
import java.util.List;/*** @author Carl* @date 2017/10/30*/
public class ValidateWebflowConfigurer extends AbstractCasWebflowConfigurer {/*** 校验码动作*/public static final String VALIDATE_CAPTCHA_ACTION = "validateCaptchaAction";public ValidateWebflowConfigurer(FlowBuilderServices flowBuilderServices, FlowDefinitionRegistry loginFlowDefinitionRegistry, ApplicationContext applicationContext, CasConfigurationProperties casProperties) {super(flowBuilderServices, loginFlowDefinitionRegistry);}@Overrideprotected void doInitialize() throws Exception {createLoginValidateValidateFlow();}/*** 登录校验流程*/private void createLoginValidateValidateFlow() {final Flow flow = getLoginFlow();if (flow != null) {final ActionState state = (ActionState) flow.getState(CasWebflowConstants.TRANSITION_ID_REAL_SUBMIT);final List<Action> currentActions = new ArrayList<>();state.getActionList().forEach(currentActions::add);currentActions.forEach(a -> state.getActionList().remove(a));state.getActionList().add(createEvaluateAction("validateLoginCaptchaAction"));currentActions.forEach(a -> state.getActionList().add(a));state.getTransitionSet().add(createTransition("captchaError", CasWebflowConstants.STATE_ID_INIT_LOGIN_FORM));}}
}

测试效果

这里写图片描述

这里写图片描述


以上代码可能不全,若有兴趣可以点击下面的连接去访问:

下载代码尝试:GitHub 其他版本可以到GitHub或者码云查看

发现一些意外的事情可以考虑翻翻前面的博客进行学习哦

作者联系方式

如果技术的交流或者疑问可以联系或者提出issue。

邮箱:huang.wenbin@foxmail.com

QQ: 756884434 (请注明:SSO-CSDN)

这篇关于CAS单点登录-登录校验码(十七)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992505

相关文章

Spring Security重写AuthenticationManager实现账号密码登录或者手机号码登录

《SpringSecurity重写AuthenticationManager实现账号密码登录或者手机号码登录》本文主要介绍了SpringSecurity重写AuthenticationManage... 目录一、创建自定义认证提供者CustomAuthenticationProvider二、创建认证业务Us

Springboot项目登录校验功能实现

《Springboot项目登录校验功能实现》本文介绍了Web登录校验的重要性,对比了Cookie、Session和JWT三种会话技术,分析其优缺点,并讲解了过滤器与拦截器的统一拦截方案,推荐使用JWT... 目录引言一、登录校验的基本概念二、HTTP协议的无状态性三、会话跟android踪技术1. Cook

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

Ubuntu 24.04启用root图形登录的操作流程

《Ubuntu24.04启用root图形登录的操作流程》Ubuntu默认禁用root账户的图形与SSH登录,这是为了安全,但在某些场景你可能需要直接用root登录GNOME桌面,本文以Ubuntu2... 目录一、前言二、准备工作三、设置 root 密码四、启用图形界面 root 登录1. 修改 GDM 配

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

Java中的登录技术保姆级详细教程

《Java中的登录技术保姆级详细教程》:本文主要介绍Java中登录技术保姆级详细教程的相关资料,在Java中我们可以使用各种技术和框架来实现这些功能,文中通过代码介绍的非常详细,需要的朋友可以参考... 目录1.登录思路2.登录标记1.会话技术2.会话跟踪1.Cookie技术2.Session技术3.令牌技

SpringBoot后端实现小程序微信登录功能实现

《SpringBoot后端实现小程序微信登录功能实现》微信小程序登录是开发者通过微信提供的身份验证机制,获取用户唯一标识(openid)和会话密钥(session_key)的过程,这篇文章给大家介绍S... 目录SpringBoot实现微信小程序登录简介SpringBoot后端实现微信登录SpringBoo

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、