cas--登录流程login-webflow.xml参考以及实时获取页面配置和自定义action
·
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/webflow"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow.xsd">
<action-state id="initialAuthenticationRequestValidationCheck">
<evaluate expression="initialAuthenticationRequestValidationAction"/>
<transition on="authenticationFailure" to="handleAuthenticationFailure"/>
<transition on="error" to="initializeLoginForm"/>
<transition on="success" to="ticketGrantingTicketCheck"/>
<transition on="successWithWarnings" to="ticketGrantingTicketCheck"/>
</action-state>
<action-state id="ticketGrantingTicketCheck">
<evaluate expression="ticketGrantingTicketCheckAction"/>
<transition on="notExists" to="gatewayRequestCheck"/>
<transition on="invalid" to="terminateSession"/>
<transition on="valid" to="hasServiceCheck"/>
<!-- ticket检查:权限校验出现异常-->
<transition on="systemAuthError" to="initializeLoginForm"/>
<!-- ticket检查:权限校验不通过,不允许访问该系统-->
<transition on="systemAuthInvalid" to="systemAuthManageCheck"/>
</action-state>
<view-state id="systemAuthManageCheck" view="systemAuthInvalid"/>
<!-- <view-state id="systemAuthError" view="systemAuthError"/>-->
<action-state id="initializeLoginForm">
<evaluate expression="initializeLoginAction"/>
<transition on="success" to="viewLoginForm"/>
</action-state>
<view-state id="viewLoginForm" view="casLoginView" model="credential">
<binder>
<binding property="username" required="true"/>
<binding property="password" required="true"/>
</binder>
<!-- 获取页面配置信息 -->
<on-entry>
<!-- viewScope 只能在视图状态中访问,而 flowScope 可以在整个流程中访问。因此,你可以将 outputViewConfig 存储在 flowScope 中,然后在决策状态中访问它。 -->
<evaluate expression="viewConfigServiceImpl.getConfig(flowRequestContext)" result="flowScope.outputViewConfig"/>
</on-entry>
<!-- invalidate:失能所有回退view,即当前及之前所有view都是不能够被回退的 -->
<!-- discard:失能一个回退view,即当前view不能再下一个view上回退,回退到的是前一个view -->
<transition on="submit" bind="true" validate="true" to="determineTargetPage" history="invalidate"/>
</view-state>
<!-- 决策状态,判断页面来源,desktop的跳转专用页面,其他的,跳转通用页面 -->
<decision-state id="determineTargetPage">
<if test="flowScope.outputViewConfig.pageType == 'desktop'" then="desktopCaptcha" else="captcha"/>
</decision-state>
<!-- desktop主题专用,校验是否需要验证码 com.demo.action.CaptchaAction-->
<action-state id="desktopCaptcha">
<evaluate expression="captchaAction"/>
<!-- 密码错误,重新回到登录页面 -->
<transition on="error" to="initializeLoginForm"/>
<!-- 密码正确,但是密码临期或已过期 -->
<transition on="needPwdWarn" to="desktopPwdWarnForm"/>
<!-- 密码正确,但是需要验证码 -->
<transition on="needCaptcha" to="desktopCaptchaForm"/>
<!-- 密码正确,并且不需要验证码 -->
<transition on="success" to="desktopRealSubmit"/>
</action-state>
<!-- 通用,校验是否需要验证码 com.demo.action.CaptchaAction-->
<action-state id="captcha">
<evaluate expression="captchaAction"/>
<!-- 密码错误,重新回到登录页面 -->
<transition on="error" to="initializeLoginForm"/>
<!-- 密码正确,但是密码临期或已过期 -->
<transition on="needPwdWarn" to="pwdWarnForm"/>
<!-- 密码正确,但是需要验证码 -->
<transition on="needCaptcha" to="captchaForm"/>
<!-- 密码正确,并且不需要验证码 -->
<transition on="success" to="realSubmit"/>
</action-state>
<!-- desktop主题专用,密码临期或已过期页面 -->
<view-state id="desktopPwdWarnForm" view="desktopPwdWarnView" model="credential">
<binder>
<binding property="username" required="true"/>
<binding property="password" required="true"/>
</binder>
<!-- 获取页面配置信息 -->
<on-entry>
<evaluate expression="viewConfigServiceImpl.getConfig(flowRequestContext)" result="viewScope.outputViewConfig"/>
</on-entry>
<!-- invalidate:失能所有回退view,即当前及之前所有view都是不能够被回退的 -->
<!-- discard:失能一个回退view,即当前view不能再下一个view上回退,回退到的是前一个view -->
<transition on="submit" bind="true" validate="true" to="desktopPwdWarn" history="invalidate"/>
</view-state>
<!-- 通用,密码临期或已过期页面 -->
<view-state id="pwdWarnForm" view="pwdWarnView" model="credential">
<binder>
<binding property="username" required="true"/>
<binding property="password" required="true"/>
</binder>
<!-- 获取页面配置信息 -->
<on-entry>
<evaluate expression="viewConfigServiceImpl.getConfig(flowRequestContext)"
result="viewScope.outputViewConfig"/>
</on-entry>
<!-- invalidate:失能所有回退view,即当前及之前所有view都是不能够被回退的 -->
<!-- discard:失能一个回退view,即当前view不能再下一个view上回退,回退到的是前一个view -->
<transition on="submit" bind="true" validate="true" to="pwdWarn" history="invalidate"/>
</view-state>
<!-- desktop主题专用,校验是否需要验证码 com.demo.action.PwdWarnAction-->
<action-state id="desktopPwdWarn">
<evaluate expression="pwdWarnAction"/>
<!-- 错误或已过期 -->
<transition on="error" to="initializeLoginForm"/>
<!-- 需要验证码 -->
<transition on="needCaptcha" to="desktopCaptchaForm"/>
<!-- 不需要验证码 -->
<transition on="success" to="desktopRealSubmit"/>
</action-state>
<!-- 通用,校验是否需要验证码 com.demo.action.PwdWarnAction-->
<action-state id="pwdWarn">
<evaluate expression="pwdWarnAction"/>
<!-- 错误或已过期 -->
<transition on="error" to="initializeLoginForm"/>
<!-- 需要验证码 -->
<transition on="needCaptcha" to="captchaForm"/>
<!-- 不需要验证码 -->
<transition on="success" to="realSubmit"/>
</action-state>
<!-- desktop主题专用,验证码页面 -->
<view-state id="desktopCaptchaForm" view="desktopCaptchaView" model="credential">
<binder>
<binding property="username" required="true"/>
<binding property="password" required="true"/>
</binder>
<!-- 获取页面配置信息 -->
<on-entry>
<evaluate expression="viewConfigServiceImpl.getConfig(flowRequestContext)" result="viewScope.outputViewConfig"/>
</on-entry>
<!-- invalidate:失能所有回退view,即当前及之前所有view都是不能够被回退的 -->
<!-- discard:失能一个回退view,即当前view不能再下一个view上回退,回退到的是前一个view -->
<transition on="submit" bind="true" validate="true" to="desktopRealSubmit" history="invalidate"/>
</view-state>
<!-- 通用,验证码页面 -->
<view-state id="captchaForm" view="captchaView" model="credential">
<binder>
<binding property="username" required="true"/>
<binding property="password" required="true"/>
</binder>
<!-- 获取页面配置信息 -->
<on-entry>
<evaluate expression="viewConfigServiceImpl.getConfig(flowRequestContext)"
result="viewScope.outputViewConfig"/>
</on-entry>
<!-- invalidate:失能所有回退view,即当前及之前所有view都是不能够被回退的 -->
<!-- discard:失能一个回退view,即当前view不能再下一个view上回退,回退到的是前一个view -->
<transition on="submit" bind="true" validate="true" to="realSubmit" history="invalidate"/>
</view-state>
<!-- desktop主题专用,真正提交表单 -->
<action-state id="desktopRealSubmit">
<evaluate expression="authenticationViaFormAction"/>
<transition on="warn" to="warn"/>
<transition on="success" to="loginState"/>
<transition on="successWithWarnings" to="showAuthenticationWarningMessages"/>
<!-- https://blog.csdn.net/cl_andywin/article/details/53380117 -->
<!-- <transition on="authenticationFailure" to="handleAuthenticationFailure"/> -->
<transition on="authenticationFailure" to="desktopErrorMsg"/>
<transition on="error" to="showAuthenticationWarningMessages"/>
</action-state>
<!-- 通用,真正提交表单 -->
<action-state id="realSubmit">
<evaluate expression="authenticationViaFormAction"/>
<transition on="warn" to="warn"/>
<transition on="success" to="loginState"/>
<transition on="successWithWarnings" to="showAuthenticationWarningMessages"/>
<!-- https://blog.csdn.net/cl_andywin/article/details/53380117 -->
<!-- <transition on="authenticationFailure" to="handleAuthenticationFailure"/> -->
<transition on="authenticationFailure" to="errorMsg"/>
<transition on="error" to="showAuthenticationWarningMessages"/>
</action-state>
<!-- desktop主题专用,错误提示信息 com.demo.action.CaptchaErrorAction -->
<action-state id="desktopErrorMsg">
<evaluate expression="errorMsgAction"/>
<transition on="success" to="desktopCaptchaForm"/>
<transition on="error" to="initializeLoginForm"/>
</action-state>
<!-- 通用,错误提示信息 com.demo.action.CaptchaErrorAction -->
<action-state id="errorMsg">
<evaluate expression="errorMsgAction"/>
<transition on="success" to="captchaForm"/>
<transition on="error" to="initializeLoginForm"/>
</action-state>
<!-- 认证成功后记录信息并生成ticket com.demo.action.LoginStateAction-->
<action-state id="loginState">
<evaluate expression="loginStateAction"/>
<transition on="success" to="sendTicketGrantingTicket"/>
</action-state>
</flow>
package com.demo.sso.service.impl;
import com.demo.sso.entity.OutputViewConfig;
import com.demo.sso.service.IViewConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apereo.cas.web.support.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.webflow.execution.RequestContext;
/**
* 页面配置项
*/
@Slf4j
@Service("viewConfigServiceImpl")
public class ViewConfigServiceImpl implements IViewConfigService {
@Autowired
private ThemeResolver themeResolver;
@Override
public OutputViewConfig getConfig(RequestContext requestContext) {
OutputViewConfig config = new OutputViewConfig();
// 获取当前登录的系统地址
String serviceUrl = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext).getParameter("service");
// 获取当前系统使用的主题
String themeName = themeResolver.resolveThemeName(WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext));
config.setPageType(themeName);
log.info("==>serviceUrl:{},themeName:{}", serviceUrl, themeName);
return config;
}
// 使用方法
// <input id="qrcodeType" th:value="${outputViewConfig.pageType}" style="display: none">
}
package com.demo.sso.action;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.web.support.WebUtils;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.stereotype.Component;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* 自定义验证码逻辑
*/
@Component
public class CaptchaAction extends AbstractAction {
@Override
protected Event doExecute(final RequestContext requestContext) {
// 是否需要验证码,true:需要,false:不需要,null:错误的直接提示“账号或密码错误”
Boolean needVerificationCode = null;
String username = StringUtils.EMPTY;
String password = StringUtils.EMPTY;
try {
final HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
Map<String, String[]> parameterMap = request.getParameterMap();
username = parameterMap.containsKey("username") ? request.getParameter("username") : StringUtils.EMPTY;
password = parameterMap.containsKey("password") ? request.getParameter("password") : StringUtils.EMPTY;
// todo 业务逻辑
} catch (Exception e) {
}
if (ssoCacheService.getAccountLockStatus(username)) {
final MessageContext messageContext = requestContext.getMessageContext();
// 当前账号已被锁定
messageContext.addMessage(new MessageBuilder().error().defaultText("当前账号已被锁定").build());
return this.error();
}
if (needVerificationCode == null) {
final MessageContext messageContext = requestContext.getMessageContext();
// 这里是页面弹窗提示信息
messageContext.addMessage(new MessageBuilder().error().defaultText("账号或密码错误").build());
return this.error();
}
return needVerificationCode ? new Event(this, "needCaptcha") : this.success();
}
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)