CAS5.3自定义登录校验规则

前一篇文章介绍过CAS自定义用户信息, 这个用户信息实在登录成功后加到session中的, 今天来介绍一下CAS5.3怎么自定义登录校验逻辑

思路

有了前一篇文章的铺垫这一次自定义登录校验其实就很简单了, 因为想要把用户信息放入到session中是一定要在登陆的时候完成的,因此这次我们需要做的就是重新写一个登录校验的逻辑

重写AbstractPreAndPostProcessingAuthenticationHandler

前一篇文章中已经用到了这个抽象类, 这次要要做的还是改造它, 我们可以在之前的基础上来改造

/**
 * 自定义登录拦截器
 *
 * @author zzt
 * @version v1.0.0
 * @date 2024/7/17
 */
@Setter
public class MyAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {

    private SysUserService sysUserService;

    public MyAuthenticationHandler(String name,
                                   ServicesManager servicesManager,
                                   PrincipalFactory principalFactory,
                                   Integer order) {
        super(name, servicesManager, principalFactory, order);
    }

    @Override
    protected AuthenticationHandlerExecutionResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {
        final UserPwdCredential originalUserPass = (UserPwdCredential) credential;
        String username = originalUserPass.getUsername();
        String password = originalUserPass.getPassword();
        String phone = originalUserPass.getPhone();
        String smsVerifyCode = originalUserPass.getSmsVerifyCode();

        //查询用户信息
        SysUser sysUser = sysUserService.getBaseMapper().selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserName, username));
        if (ObjectUtils.isNotEmpty(sysUser)) {
            if (StringUtils.equals(username, sysUser.getUserName()) &&
                    StringUtils.equals(PasswordUtil.getPassword(password, sysUser.getSalt()), sysUser.getPassword())) {
                if (Objects.equals(sysUser.getPhone(), phone) && StringUtils.isNotBlank(smsVerifyCode)) {
//仅判断用户是否输入了自己的手机号,需要自行修改
                    return createHandlerResult(credential,
                            this.principalFactory.createPrincipal(username), Collections.emptyList());
                } else {
                    throw new RuntimeException("验证码错误");
                }
            } else {
                throw new RuntimeException("用户名或密码错误");
            }
     

        } else {
            throw new RuntimeException("用户不存在");
        }

    }

    @Override
    public boolean supports(Credential credential) {
        return credential instanceof UserPwdCredential;
    }
}

这里逻辑其实很简单, 就是验证完用户名密码之后还要验证手机号验证码, 我们常用到的双因子认证, 之前文章中有提到过下面这个方法,请继续往下看

Credential

这里是CAS默认登录逻辑的参数, 仅有用户名和密码, 在上一篇文章中也有提到过这里其实是一个策略模式, 因此我们只需要继承UsernamePasswordCredential类就可以了, 注意这里前端在给后端传参时一定要是这四个属性, 不然是无法进入到我们这个实现类的, 在这里我卡了挺长时间

继承后的实现

/**
 * 自定义登录参数
 *
 * @author zzt
 * @version v1.0.0
 * @date 2024/7/17
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class UserPwdCredential extends UsernamePasswordCredential {


    @Size(min = 1, message = "手机号不能为空!")
    private String phone;

    @Size(min = 1, message = "验证码不能为空!")
    private String smsVerifyCode;
}

 继承DefaultLoginWebflowConfigurer

/**
 * 自定义登录
 *
 * @author zzt
 * @version v1.0.0
 * @date 2024/7/17
 */
public class CustomLoginWebflowConfigurer extends DefaultLoginWebflowConfigurer {


    public CustomLoginWebflowConfigurer(FlowBuilderServices flowBuilderServices, FlowDefinitionRegistry flowDefinitionRegistry, ApplicationContext applicationContext, CasConfigurationProperties casProperties) {
        super(flowBuilderServices, flowDefinitionRegistry, applicationContext, casProperties);
    }

    @Override
    protected void createRememberMeAuthnWebflowConfig(Flow flow) {
            createFlowVariable(flow, CasWebflowConstants.VAR_ID_CREDENTIAL, UserPwdCredential.class);
            final ViewState state = getState(flow, CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM, ViewState.class);
            final BinderConfiguration cfg = getViewStateBinderConfiguration(state);
            cfg.addBinding(new BinderConfiguration.Binding("phone", null, true));
            cfg.addBinding(new BinderConfiguration.Binding("smsVerifyCode", null, true));

    }
}

 我们还需要把要接收的这两个新参数添加到这里来

改前端

这里的前端页面用到的是webflow技术, 还是比较老的, 因此改起来比较麻烦,这里我们就参考原来的写法,给它新加参数即可

修改 resources/template/loginfrom.html

<section class="form-group form-grouptwo">
<!--                            <label for="username" th:utext="#{screen.welcome.label.netid}">Username</label>-->
                            <div th:if="${openIdLocalId}">
                                <strong>
                                    <span th:utext="${openIdLocalId}"/>
                                </strong>
                                <input type="hidden"
                                       id="username"
                                       name="username"
                                       th:value="${openIdLocalId}"/>
                            </div>
                            <div th:unless="${openIdLocalId}" class="input-group">
                                <div class="input-group-prepend">
                                <span class="input-group-text">
                                    <img th:src="@{images/zhanghao.png}" alt="Username Icon"/>
                                </span>
                                </div>
                                <input class="form-control required form-place"
                                       id="username"
                                       size="25"
                                       tabindex="1"
                                       placeholder="请输入登录账号"
                                       type="text"
                                       th:disabled="${guaEnabled}"
                                       th:field="*{username}"
                                       th:accesskey="#{screen.welcome.label.netid.accesskey}"
                                       autocomplete="off"/>
                            </div>
                        </section>

                        <section class="form-group form-grouptwo">
<!--                            <label for="password" th:utext="#{screen.welcome.label.password}">Password</label>-->

                            <div class="input-group">
                                <div class="input-group-prepend">
                                <span class="input-group-text">
<!--                                    <img src="path/to/your/image.png" alt="Password Icon" width="20" height="20">-->
                                     <img th:src="@{images/mima.png}" alt="Password Icon"/>
                                </span>
                                </div>
                                <input class="form-control required form-place"
                                       type="password"
                                       id="password"
                                       size="25"
                                       tabindex="2"
                                       placeholder="请输入登录密码"
                                       th:accesskey="#{screen.welcome.label.password.accesskey}"
                                       th:field="*{password}"
                                       autocomplete="off"/>
                                <span id="capslock-on" style="display:none;">
                                <p>
                                    <i class="fa fa-exclamation-circle"></i>
                                    <span th:utext="#{screen.capslock.on}"/>
                                </p>
                            </span>
                            </div>
                        </section>
<!--                        手机-->
                        <section class="form-group form-grouptwo">
                            <!--                            <label for="password" th:utext="#{screen.welcome.label.password}">Password</label>-->
                            <div class="input-group">
                                <div class="input-group-prepend">
                                <span class="input-group-text">
<!--                                    <img src="path/to/your/image.png" alt="Password Icon" width="20" height="20">-->
                                     <img th:src="@{images/shoujihao.png}" alt="shoujihao Icon"/>
                                </span>
                                </div>
                                <input class="form-control required form-place"
                                       type="text"
                                       id="phone"
                                       th:field="*{phone}"
                                       size="25"
                                       tabindex="3"
                                       placeholder="请输入手机号码"
                                       autocomplete="off"/>
                                <span id="capslock-on" style="display:none;">
                                <p>
                                    <i class="fa fa-exclamation-circle"></i>
                                    <span th:utext="#{screen.capslock.on}"/>
                                </p>
                            </span>
                            </div>
                        </section>

                        <!--验证码-->
                        <section class="form-group form-grouptwo">
                            <!--                            <label for="password" th:utext="#{screen.welcome.label.password}">Password</label>-->
                            <div class="input-group">
                                <div class="input-group-prepend">
                                <span class="input-group-text">
<!--                                    <img src="path/to/your/image.png" alt="Password Icon" width="20" height="20">-->
                                     <img th:src="@{images/yanzhengma.png}" alt="smsVerifyCode Icon"/>
                                </span>
                                </div>
                                <input class="form-control required form-place form-absolute"
                                       type="text"
                                       id="smsVerifyCode"
                                       th:field="*{smsVerifyCode}"
                                       size="25"
                                       tabindex="4"
                                       placeholder="请输入验证码"
                                       autocomplete="off"/>
                                <button class="form-sendbutton" id="sendCodeBtn">发送验证码</button>
                                <span id="countdown" class="countdown"></span>
                                <span id="capslock-on" style="display:none;">
                                <p>
                                    <i class="fa fa-exclamation-circle"></i>
                                    <span th:utext="#{screen.capslock.on}"/>
                                </p>
                            </span>
                            </div>
                        </section>

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Cas 5.3 pac4j是一个用于身份验证和授权的Java库。它提供了一种简单且可扩展的方式来集成CAS(Central Authentication Service)协议和pac4j库,用于集中身份验证。CAS是一种单点登录协议,它允许用户在一次登录后访问多个应用程序而无需再次登录。pac4j是一个Java库,用于实现身份验证和授权的安全框架。 使用Cas 5.3 pac4j,开发人员可以轻松地实现CAS协议和pac4j库的集成,并集中管理用户的身份验证和授权。它提供了多种身份验证方法,包括用户名密码,OAuth,OpenID等。开发人员只需配置相应的身份验证器即可使用这些方法。 该库还提供了丰富的授权机制,允许开发人员定义访问控制规则,以决定哪些用户可以访问特定资源。这些规则可以基于用户角色,用户组,IP地址等进行配置,并通过简单的配置文件进行管理。 Cas 5.3 pac4j还支持自定义的身份验证器和授权器,使开发人员可以根据自己的需要进行扩展和定制。此外,它还提供了易于使用的API,方便开发人员在应用程序中使用身份验证和授权功能。 总之,Cas 5.3 pac4j提供了一个强大而灵活的身份验证和授权解决方案,帮助开发人员快速集成CAS协议和pac4j库,并集中管理用户的身份验证和授权。 ### 回答2: Cas 5.3是一个开源的单点登录(SSO)协议,用于统一认证和授权系统。Pac4j是一个在Cas 5.3上构建的Java安全库。 Cas是“Central Authentication Service”的缩写,主要用于企业或组织中的应用程序和服务之间的身份验证问题。Cas 5.3Cas协议的一个版本,它提供了多种身份验证方式,包括用户名/密码、第三方账号、Token和验证码等。它的核心原理是通过一个中央认证服务器来验证用户的身份,并将认证结果传递给各个应用程序,实现了用户在一个应用中登录后,其身份在其他应用中的自动认证。 Pac4j是一个开源的Java安全库,它在Cas 5.3上提供了更强大和灵活的安全功能。Pac4j可以集成多种身份验证方式,包括Cas、OAuth、SAML、OpenID Connect、LDAP和JWT等,并能够与各种框架(如Spring、Play、Vert.x)无缝集成。Pac4j还支持身份授权和权限管理,可以根据用户的角色和权限对资源进行访问控制。 Cas 5.3和Pac4j的结合可以实现一个健全的身份认证和授权体系。它们可以应用于各种场景,如企业内部应用的统一登录、多租户系统的身份管理和第三方应用的认证授权等。通过使用Cas 5.3和Pac4j,可以大大简化安全开发的复杂性,提高系统的安全性和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值