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

相关文章

Oracle数据库如何切换登录用户(system和sys)

《Oracle数据库如何切换登录用户(system和sys)》文章介绍了如何使用SQL*Plus工具登录Oracle数据库的system用户,包括打开登录入口、输入用户名和口令、以及切换到sys用户的... 目录打开登录入口登录system用户总结打开登录入口win+R打开运行对话框,输php入:sqlp

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

校验码:奇偶校验,CRC循环冗余校验,海明校验码

文章目录 奇偶校验码CRC循环冗余校验码海明校验码 奇偶校验码 码距:任何一种编码都由许多码字构成,任意两个码字之间最少变化的二进制位数就称为数据检验码的码距。 奇偶校验码的编码方法是:由若干位有效信息(如一个字节),再加上一个二进制位(校验位)组成校验码。 奇校验:整个校验码中1的个数为奇数 偶校验:整个校验码中1的个数为偶数 奇偶校验,可检测1位(奇数位)的错误,不可纠错。

Shell脚本实现自动登录服务器

1.登录脚本 login_server.sh #!/bin/bash# ReferenceLink:https://yq.aliyun.com/articles/516347#show all host infos of serverList.txtif [[ -f ./serverList.txt ]]thenhostNum=`cat ./serverList.txt | wc -l`e

SpringBoot登录退出|苍穹外卖登录退出分析

文章目录 概要整体流程注意事项一、拦截路径二、token三、注册防止用户重复提交 苍穹外卖登录退出分析注意解决JWT退出后依然有效的问题 概要 结合Spring Boot和Vue3实现安全的用户登录和退出功能,并使用拦截器、JWT和Redis缓存来提高系统的安全性和性能。 整体流程 注意事项 一、拦截路径 像登录页面的路径就不要拦截了,否则都不能登录了 例如:

Node.js和vue3实现GitHub OAuth第三方登录

Node.js和vue3实现GitHub OAuth第三方登录 前言 第三方登入太常见了,微信,微博,QQ…总有一个你用过。 在开发中,我们希望用户可以通过GitHub账号登录我们的网站,这样用户就不需要注册账号,直接通过GitHub账号登录即可。 效果演示 注册配置 GitHub 应用 1.首先登录你的GitHub然后点击右上角的头像->点击进入Settings页面 2.在

三方登录 - 华为登录

1.1. 开发准备 当应用需要使用以下开放能力的一种或多种时,为正常调试运行应用,需要预先添加公钥指纹 Account Kit(华为帐号服务)Call Kit(通话服务)Game Service Kit(游戏服务)Health Service Kit(运动健康服务)IAP Kit(应用内支付服务)Live View Kit(实况窗服务,当需要使用Push Kit时必须执行此步骤)Map Kit