CAS单点登录:配置记住我,添加验证码(五)

news/2024/9/29 13:30:24

1.配置RememberMe

1.1.修改application.properties

##
# 记住我
#
cas.ticket.tgt.rememberMe.enabled=true
cas.ticket.tgt.rememberMe.timeToKillInSeconds=3600

1.2.修改登录界面

<div class="form-group" th:if="${rememberMeAuthenticationEnabled}"><input type="checkbox" name="rememberMe" id="rememberMe" value="true" tabindex="5"/><label for="rememberMe" th:text="#{screen.rememberme.checkbox.title}">Remember Me</label>
</div>

1.3.测试流程

第一步:首先 不选择记住我登录 然后退出浏览器。

第二步:打开浏览器,再次访问服务 发现需要登录。

第三步:选择 记住我登录,然后退出浏览器。

第四步:打开浏览器,访问服务,直接就是登录成功状态。(前提是退出浏览器前不要登出)

2.添加验证码

从页面登录页面上我们可以知道,登陆的用户名和密码信息绑定到了credential这个对象上的。

如果开启了RememberMe的功能就使用RememberMeUsernamePasswordCredential。

如果没有就使用UsernamePasswordCredential了,这里我们使用RememberMeUsernamePasswordCredential。

2.1.添加依赖

复制代码
<dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-core-authentication</artifactId><version>${cas.version}</version>
</dependency>
<dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-core-authentication-api</artifactId><version>${cas.version}</version>
</dependency>
<dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-core-webflow</artifactId><version>${cas.version}</version>
</dependency>
<dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-core-webflow-api</artifactId><version>${cas.version}</version>
</dependency>
复制代码

这里可能会在后续继承DefaultLoginWebflowConfigurer时无法导入依赖

虽然cas-server-core-webflow中有那个类,但是无法导入,所以单独引入cas-server-core-webflow-api这个依赖

2.2.重写credential

复制代码
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apereo.cas.authentication.RememberMeUsernamePasswordCredential;public class RememberMeUsernamePasswordCaptchaCredential extends RememberMeUsernamePasswordCredential {private String captcha;public String getCaptcha() {return captcha;}public void setCaptcha(String captcha) {this.captcha = captcha;}@Overridepublic int hashCode() {return new HashCodeBuilder().appendSuper(super.hashCode()).append(this.captcha).toHashCode();}
}
复制代码

2.3.新建DefaultCaptchaWebflowConfigurer修改之前默认的Credential

复制代码
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.web.flow.CasWebflowConstants;
import org.apereo.cas.web.flow.configurer.DefaultLoginWebflowConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.ViewState;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;public class DefaultCaptchaWebflowConfigurer extends DefaultLoginWebflowConfigurer {public DefaultCaptchaWebflowConfigurer(FlowBuilderServices flowBuilderServices, FlowDefinitionRegistry flowDefinitionRegistry, ApplicationContext applicationContext, CasConfigurationProperties casProperties) {super(flowBuilderServices, flowDefinitionRegistry, applicationContext, casProperties);}@Overrideprotected void createRememberMeAuthnWebflowConfig(Flow flow) {if (casProperties.getTicket().getTgt().getRememberMe().isEnabled()) {createFlowVariable(flow, CasWebflowConstants.VAR_ID_CREDENTIAL, RememberMeUsernamePasswordCaptchaCredential.class);final ViewState state = getState(flow, CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM, ViewState.class);final BinderConfiguration cfg = getViewStateBinderConfiguration(state);cfg.addBinding(new BinderConfiguration.Binding("rememberMe", null, false));cfg.addBinding(new BinderConfiguration.Binding("captcha", null, true));} else {createFlowVariable(flow, CasWebflowConstants.VAR_ID_CREDENTIAL, UsernamePasswordCredential.class);final ViewState state = getState(flow, CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM, ViewState.class);final BinderConfiguration cfg = this.getViewStateBinderConfiguration(state);cfg.addBinding(new BinderConfiguration.Binding("captcha", null, true));}}
}
复制代码

2.4.创建表单处理器

复制代码
import com.fdzang.cas.service.framework.ApiResult;
import com.fdzang.cas.service.service.UserService;
import com.fdzang.cas.service.util.Constant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.RegisteredService;
import org.apereo.cas.services.ServicesManager;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.security.auth.login.FailedLoginException;
import javax.servlet.http.HttpServletRequest;
import java.security.GeneralSecurityException;@Slf4j
public class RememberMeUsernamePasswordCaptchaAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {private UserService userService;public RememberMeUsernamePasswordCaptchaAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {super(name, servicesManager, principalFactory, order);}@Overrideprotected AuthenticationHandlerExecutionResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();RememberMeUsernamePasswordCaptchaCredential captchaCredential = (RememberMeUsernamePasswordCaptchaCredential) credential;String requestCaptcha = captchaCredential.getCaptcha();String username = captchaCredential.getUsername();String password = captchaCredential.getPassword();// 校验验证码Object attribute = request.getSession().getAttribute(Constant.CAPTCHA_SESSION_KEY);String realCaptcha = attribute == null ? null : attribute.toString();if(StringUtils.isBlank(requestCaptcha) || !requestCaptcha.equalsIgnoreCase(realCaptcha)){throw new FailedLoginException("验证码错误");}// 获取请求来源URLString referer = request.getHeader("referer");if(referer.indexOf("service=")>0){referer = referer.substring(referer.indexOf("service=")+8);referer.replace("%3A",":");referer.replace("%2F","/");}RegisteredService service = findByServiceId(referer);if (service != null){throw new FailedLoginException("未查询到Service错误");}String appCode = service.getName();// 登录校验ApiResult result = userService.userLogin(username,password,appCode);if(!result.getCode().equals(0L)){throw new FailedLoginException(result.getMsg());}return createHandlerResult(credential, this.principalFactory.createPrincipal(username));}@Overridepublic boolean supports(Credential credential) {return credential instanceof RememberMeUsernamePasswordCaptchaCredential;}public RegisteredService findByServiceId(String serviceId){RegisteredService service = null;try {service = servicesManager.findServiceBy(serviceId);} catch (Exception e) {log.error(e.getMessage());}return service;}public void setUserService(UserService userService) {this.userService = userService;}
}
复制代码

这里我根据自己的需求做了特定的登录校验,仅做参考。

2.5.配置DefaultCaptchaWebflowConfigurer 

复制代码
import com.fdzang.cas.service.captcha.DefaultCaptchaWebflowConfigurer;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.web.flow.CasWebflowConfigurer;
import org.apereo.cas.web.flow.config.CasWebflowContextConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;@Configuration("captchaWebflowConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
@AutoConfigureBefore(value = CasWebflowContextConfiguration.class)
public class CaptchaWebflowConfiguration {@Autowired@Qualifier("loginFlowRegistry")private FlowDefinitionRegistry loginFlowRegistry;@Autowiredprivate ApplicationContext applicationContext;@Autowiredprivate CasConfigurationProperties casProperties;@Autowired@Qualifier("builder")private FlowBuilderServices builder;@Bean("defaultLoginWebflowConfigurer")public CasWebflowConfigurer defaultLoginWebflowConfigurer() {DefaultCaptchaWebflowConfigurer c = new DefaultCaptchaWebflowConfigurer(builder, loginFlowRegistry, applicationContext, casProperties);c.initialize();return c;}
}
复制代码

2.6.配置表单处理器

复制代码
import com.fdzang.cas.service.captcha.RememberMeUsernamePasswordCaptchaAuthenticationHandler;
import com.fdzang.cas.service.service.UserService;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
import org.apereo.cas.authentication.AuthenticationHandler;
import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.services.ServicesManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration("rememberMeConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class RememberMeCaptchaConfiguration implements AuthenticationEventExecutionPlanConfigurer {@Autowired@Qualifier("servicesManager")private ServicesManager servicesManager;@Autowiredprivate UserService userService;@Beanpublic AuthenticationHandler rememberMeUsernamePasswordCaptchaAuthenticationHandler() {RememberMeUsernamePasswordCaptchaAuthenticationHandler handler = new RememberMeUsernamePasswordCaptchaAuthenticationHandler(RememberMeUsernamePasswordCaptchaAuthenticationHandler.class.getSimpleName(),servicesManager,new DefaultPrincipalFactory(),9);handler.setUserService(userService);return handler;}@Overridepublic void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {plan.registerAuthenticationHandler(rememberMeUsernamePasswordCaptchaAuthenticationHandler());}
}
复制代码

2.7.加载配置类,spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.apereo.cas.config.CasEmbeddedContainerTomcatConfiguration,\org.apereo.cas.config.CasEmbeddedContainerTomcatFiltersConfiguration,\com.fdzang.cas.service.config.SpringConfig,\com.fdzang.cas.service.config.RememberMeCaptchaConfiguration,\com.fdzang.cas.service.config.CaptchaWebflowConfiguration

2.8.验证码生成工具类

复制代码
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;public class CaptchaUtil {// 随机产生的字符串private static final String RANDOM_STRS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";private static final String FONT_NAME = "Fixedsys";private static final int FONT_SIZE = 18;private Random random = new Random();private int width = 80;// 图片宽private int height = 25;// 图片高private int lineNum = 50;// 干扰线数量private int strNum = 4;// 随机产生字符数量/*** 生成随机图片*/public BufferedImage genRandomCodeImage(StringBuffer randomCode) {BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_BGR);Graphics g = image.getGraphics();g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);g.setColor(getRandColor(110, 120));for (int i = 0; i <= lineNum; i++) {drowLine(g);}// 绘制随机字符g.setFont(new Font(FONT_NAME, Font.ROMAN_BASELINE, FONT_SIZE));for (int i = 1; i <= strNum; i++) {randomCode.append(drowString(g, i));}g.dispose();return image;}/*** 给定范围获得随机颜色*/private Color getRandColor(int fc, int bc) {if (fc > 255){fc = 255;}if (bc > 255){bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}/*** 绘制字符串*/private String drowString(Graphics g, int i) {g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));String rand = String.valueOf(getRandomString(random.nextInt(RANDOM_STRS.length())));g.translate(random.nextInt(3), random.nextInt(3));g.drawString(rand, 13 * i, 16);return rand;}/*** 绘制干扰线*/private void drowLine(Graphics g) {int x = random.nextInt(width);int y = random.nextInt(height);int x0 = random.nextInt(16);int y0 = random.nextInt(16);g.drawLine(x, y, x + x0, y + y0);}/*** 获取随机的字符*/private String getRandomString(int num) {return String.valueOf(RANDOM_STRS.charAt(num));}
}
复制代码

2.9.验证码控制层

复制代码
import com.fdzang.cas.service.util.CaptchaUtil;
import com.fdzang.cas.service.util.Constant;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;@RestController
public class CaptchaController {@GetMapping("/captcha.jpg")public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("image/jpeg");response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expire", 0);try {HttpSession session = request.getSession();CaptchaUtil tool = new CaptchaUtil();StringBuffer code = new StringBuffer();BufferedImage image = tool.genRandomCodeImage(code);session.removeAttribute(Constant.CAPTCHA_SESSION_KEY);session.setAttribute(Constant.CAPTCHA_SESSION_KEY, code.toString());// 将内存中的图片通过流动形式输出到客户端ImageIO.write(image, "JPEG", response.getOutputStream());} catch (Exception e) {e.printStackTrace();}}
}
复制代码

2.10.修改登录页面

复制代码
<div class="form-group"><label for="captcha">验证码:</label><input class="required" id="captcha" name="captcha" size="10"tabindex="2" th:field="*{captcha}" autocomplete="off"/><img th:src="@{/captcha.jpg}" id="captcha_img" onclick="javascript:refreshCaptcha()"/>
</div><script type="text/javascript">function refreshCaptcha(){$("#captcha_img").attr("src","/cas/captcha.jpg?id=" + new Date() + Math.floor(Math.random()*24));}
</script>
复制代码

2.11.注释默认登录逻辑

#cas.authn.accept.users=admin::123456

 

 

 

 

 

参考:https://blog.csdn.net/qq_34021712/article/details/82259101

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/45419.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

解决Jenkins用shell脚本部署后,Jenkins自动杀掉启衍生出来的守护进程

参考 https://www.cnblogs.com/chenchen-tester/p/9334482.html 使用jenkins部署后jenkins会自动kill部署脚本导致部署不成功 可以使用以下方法解决 在部署shell脚本之前添加参数 BUILD_ID=DONTKILLME

CAS单点登录:动态添加service(四)

1.简介 在CAS系统中,主要分为三部分,User、Web应用、SSO认证中心。 User就是我们普通用户,Web应用就是需要接入SSO认证中心的应用也就是这里的Service,而SSO认证中心就是CAS服务端。 简单来说就是CAS分为服务端和客户端,而Service就是指具体的多个客户端(CAS Clients)。…

linux命令lshw

lshw是一个提取机器硬件配置详细信息的小工具。 它可以在DMI卡上报告准确的内存配置、固件版本、主板配置、CPU版本和速度、缓存配置、总线速度等,可支持x86或IA-64系统,并且在一些PowerPC机器上(已知PowerMac G4可以工作)。用法 ​ lshw [指定格式] [指定参数] 格式选项 -h…

CAJ文件怎么打开?可以转成word吗?

随着科技的发展,文档格式的多样性成为我们日常工作中不可避免的一部分。CAJ文件,作为一种特殊的文档格式,常常困扰着许多用户。那么,究竟什么是CAJ文件格式?我们又该如何将其转换为常用的Word文档呢?接下来,让我们一起深入了解。 打开CAJ文档非常简单,只需要下载官方的…

自定义F类中U类指针管理(UEC++CollectGarbage)

UObject 系统和垃圾回收 UObject:UObject及子类由UE的垃圾回收(GC)系统管理。UE使用引用计数来跟踪对象的生命周期。当一个UObject实例不再被任何强引用持有时,GC会将其标记为可回收。 标记-清除(Mark-and-Sweep):UE的GC系统采用标记-清除算法,这类似于C#和Java的GC机制…

Libgdx游戏开发(3)——通过柏林噪音算法地图随机地形

原文: Libgdx游戏开发(3)——通过柏林噪音算法地图随机地形-Stars-One的杂货小窝 在B站刷到了随机地图生成的视频,随手学习下并做下记录注: 本篇使用javafx应用作演示,算是了解这个算法的使用,后续会再出篇libgdx生成地图的示例说明 抛开算法实现,首先认知柏林噪音算法 一般我们…

MyBatis 关于查询语句上配置的详细内容

1. MyBatis 关于查询语句上配置的详细内容 @目录1. MyBatis 关于查询语句上配置的详细内容2. 准备工作3. SQL查询结果,返回为POJO实体类型4. SQL查询结果,返回为List<POJO> 集合类型5. SQL查询结果,返回为Map 集合6. SQL查询结果,返回为List<Map>集合7. SQL查询…

PC端抓包-.exe程序

一、工具 Proxifier:https://files.cnblogs.com/files/blogs/679179/Proxifier-Lit.zip?t=1717655967&download=true+ Charles:https://www.charlesproxy.com二、配置 1、Charles配置 ➭ 勾选Windows Proxy ➭ 点击Proxy Settings,定义一个代理端口(默认8888) 2、Pr…