`

cas 自定义登陆异常提示

阅读更多

自定义登录错误提示消息

CAS核心类CentralAuthenticationServiceImpl负责进行登录认证、创建TGTST、验证票据等逻辑,该类中注册了CAS认证管理器AuthenticationManager,对应bean的配置如下:

复制代码
    <bean id="centralAuthenticationService" class="org.jasig.cas.CentralAuthenticationServiceImpl"
        p:ticketGrantingTicketExpirationPolicy-ref="grantingTicketExpirationPolicy"
        p:serviceTicketExpirationPolicy-ref="serviceTicketExpirationPolicy"
        p:authenticationManager-ref="authenticationManager"
        p:ticketGrantingTicketUniqueTicketIdGenerator-ref="ticketGrantingTicketUniqueIdGenerator"
        p:ticketRegistry-ref="ticketRegistry" p:servicesManager-ref="servicesManager"
        p:persistentIdGenerator-ref="persistentIdGenerator"
        p:uniqueTicketIdGeneratorsForService-ref="uniqueIdGeneratorsMap" />
复制代码

CentralAuthenticationServiceImpl中的方法负责调用AuthenticationManager进行认证,并捕获AuthenticationException类型的异常,如创建ST的方法grantServiceTicket代码示例如下:

复制代码
    if (credentials != null) {
        try {
            final Authentication authentication = this.authenticationManager
                .authenticate(credentials);
            final Authentication originalAuthentication = ticketGrantingTicket.getAuthentication();
    
            if (!(authentication.getPrincipal().equals(originalAuthentication.getPrincipal()) && authentication.getAttributes().equals(originalAuthentication.getAttributes()))) {
                throw new TicketCreationException();
            }
        } catch (final AuthenticationException e) {
            throw new TicketCreationException(e);
        }
    }
复制代码

在CAS WEBFLOW流转的过程中,对应的action就会捕获这些TicketCreationException,并在表单中显示该异常信息。

如org.jasig.cas.web.flow.AuthenticationViaFormAction类中的表单验证方法代码如下:

复制代码
    public final String submit(final RequestContext context, final Credentials credentials, final MessageContext messageContext) throws Exception {
        final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
        final Service service = WebUtils.getService(context);
    
        if (StringUtils.hasText(context.getRequestParameters().get("renew")) && ticketGrantingTicketId != null && service != null) {
    
            try {
                final String serviceTicketId = this.centralAuthenticationService.grantServiceTicket(ticketGrantingTicketId, service, credentials);
                WebUtils.putServiceTicketInRequestScope(context, serviceTicketId);
                putWarnCookieIfRequestParameterPresent(context);
                return "warn";
            } catch (final TicketException e) {
                if (e.getCause() != null && AuthenticationException.class.isAssignableFrom(e.getCause().getClass())) {
                    populateErrorsInstance(e, messageContext);
                    return "error";
                }
                this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
                if (logger.isDebugEnabled()) {
                    logger.debug("Attempted to generate a ServiceTicket using renew=true with different credentials", e);
                }
            }
        }
    
        try {
            WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
            putWarnCookieIfRequestParameterPresent(context);
            return "success";
        } catch (final TicketException e) {
            populateErrorsInstance(e, messageContext);
            return "error";
        }

}
复制代码

因此在自定义的AuthenticationHandler类的验证方法中抛出继承自AuthenticationException的异常,登录页面(默认为WEB-INF/view/jsp/default/ui/casLoginView.jsp)中的Spring Security验证表单将会自动输出该异常对应的错误消息。

CAS AuthenticationException结构如下图,CAS已经内置了一些异常,比如用户名密码错误、未知的用户名错误等。

假设这样一个需求:用户注册时需要验证邮箱才能登录,如果未验证邮箱,则提示用户还未验证邮箱,拒绝登录。

为实现未验证邮箱后提示用户的需求,定义一个继承自AuthenticationException的类:UnRegisterEmailAuthenticationException,代码示例如下:

复制代码
    package test;
    
    import org.jasig.cas.authentication.handler.BadUsernameOrPasswordAuthenticationException;
    
    public class UnRegisterEmailAuthenticationException extends BadUsernameOrPasswordAuthenticationException {
        /** Static instance of UnknownUsernameAuthenticationException. */
        public static final UnRegisterEmailAuthenticationException ERROR = new UnRegisterEmailAuthenticationException();
    
        /** Unique ID for serializing. */
        private static final long serialVersionUID = 3977861752513837361L;
    
        /** The code description of this exception. */
        private static final String CODE = "error.authentication.credentials.bad.unregister.email";
    
        /**
         * Default constructor that does not allow the chaining of exceptions and
         * uses the default code as the error code for this exception.
         */
        public UnRegisterEmailAuthenticationException() {
            super(CODE);
        }
    
        /**
         * Constructor that allows for the chaining of exceptions. Defaults to the
         * default code provided for this exception.
         *
         * @param throwable the chained exception.
         */
        public UnRegisterEmailAuthenticationException(final Throwable throwable) {
            super(CODE, throwable);
        }
    
        /**
         * Constructor that allows for providing a custom error code for this class.
         * Error codes are often used to resolve exceptions into messages. Providing
         * a custom error code allows the use of a different message.
         *
         * @param code the custom code to use with this exception.
         */
        public UnRegisterEmailAuthenticationException(final String code) {
            super(code);
        }
    
        /**
         * Constructor that allows for chaining of exceptions and a custom error
         * code.
         *
         * @param code the custom error code to use in message resolving.
         * @param throwable the chained exception.
         */
        public UnRegisterEmailAuthenticationException(final String code,
            final Throwable throwable) {
            super(code, throwable);
        }
    }
复制代码

请注意代码中的CODE私有属性,该属性定义了一个本地化资源文件中的键,通过该键获取本地化资源中对应语言的文字,这里只实现中文错误消息提示,修改WEB-INF/classes/messages_zh_CN.properties文件,添加CODE定义的键值对,如下示例:

error.authentication.credentials.bad.unregister.email=\u4f60\u8fd8\u672a\u9a8c\u8bc1\u90ae\u7bb1\uff0c\u8bf7\u5148\u9a8c\u8bc1\u90ae\u7bb1\u540e\u518d\u767b\u5f55

后面的文字是使用native2ascii工具编码转换的中文错误提示。

接下来只需要在自定义的AuthenticationHandler类的验证方法中,验证失败的地方抛出异常即可。

自定义AuthenticationHandler示例代码如下:

复制代码
    package cn.test.web;
    
    import javax.validation.constraints.NotNull;
    
    import org.jasig.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler;
    import org.jasig.cas.authentication.handler.AuthenticationException;
    import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
    import org.springframework.dao.IncorrectResultSizeDataAccessException;
    
    public class CustomQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
    
        @NotNull
        private String sql;
    
        @Override
        protected boolean authenticateUsernamePasswordInternal(UsernamePasswordCredentials credentials) throws AuthenticationException {
            final String username = getPrincipalNameTransformer().transform(credentials.getUsername());
            final String password = credentials.getPassword();
            final String encryptedPassword = this.getPasswordEncoder().encode(password);
    
            try {
    
                // 查看邮箱是否已经验证。
                Boolean isEmailValid= EmailValidation.Valid();

                if(!isEmailValid){
                    throw new UnRegisterEmailAuthenticationException();
                }
    
                //其它验证
                ……
    
            } catch (final IncorrectResultSizeDataAccessException e) {
                // this means the username was not found.
                return false;
            }
        }
    
        public void setSql(final String sql) {
            this.sql = sql;
        }
    }
复制代码

 

三、配置使自定义登录认证生效

最后需要修改AuthenticationManager bean的配置(一般为修改WEB-INF/spring-configuration/applicationContext.xml文件),加入自定义的AuthenticationHandler,配置示例如下:

复制代码
    <bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl">
        <property name="credentialsToPrincipalResolvers">
            <list>
                <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver">
                    <property name="attributeRepository" ref="attributeRepository" />
                </bean>
                <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
            </list>
        </property>
    
        <property name="authenticationHandlers">
            <list>
                <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
                    p:httpClient-ref="httpClient" p:requireSecure="false" />
                <bean class="cn.test.web.CustomQueryDatabaseAuthenticationHandler">
                    <property name="sql" value="select password from t_user where user_name=?" />
                    <property name="dataSource" ref="dataSource" />
                    <property name="passwordEncoder" ref="passwordEncoder"></property>
                </bean>
            </list>
        </property>
    </bean>
复制代码
 
 
参考原文地址:
http://www.cnblogs.com/gao241/p/3367805.html
分享到:
评论

相关推荐

    shiro整合cas的实例

    此时,你需要捕获 `AuthenticationException` 类型的异常,并采取相应的处理措施,如提示用户重新登录。 7. **测试与调试** - 配置完成后,进行单元测试和集成测试,确保 CAS 认证流程正常工作,包括登录、登出、...

    CAS_SSO单点登录实例详细步骤

    2. 输入keystore密码,例如`sunjuncai`,然后根据提示提供个人信息,如域名(应与服务器实际域名一致,否则可能导致异常)。 3. 导出证书: 命令:`keytool -export -file c:/store/server.crt -alias sjc -...

    CAS单点登录.

    - **异常处理**:正确处理CAS通信失败的情况,例如网络问题或服务器故障,需要有优雅的降级策略,避免用户无法访问应用。 - **用户体验**:设计友好的登录界面和流程,减少用户的困扰。例如,提供清晰的登录状态...

    cas(绝对原创的SSO)

    在这个压缩包中,你将找到关于如何使用CAS进行自定义验证和异常处理的原创研究。 首先,我们要理解CAS的基本工作流程。当用户尝试访问一个受CAS保护的资源时,会被重定向到CAS服务器进行身份验证。如果用户已经登录...

    cas单点登录相关资料

    - **异常处理**:考虑如何处理认证失败、网络中断等情况,提供友好的错误提示。 总的来说,CAS单点登录是一个强大且灵活的身份验证解决方案,有助于构建安全、便捷的多应用环境。理解和掌握CAS的工作原理以及实施...

    我的CAS配置及测试过程

    4. **异常处理**:测试在凭证错误、网络中断等情况下的错误处理和提示。 5. **多应用测试**:确保用户在登录一次后,可以无阻碍地访问所有已集成CAS的其他应用。 在提供的压缩包中,包含了"我的CAS配置测试流程...

    shrio Cas 集成

    2. **创建 CAS Filter**:在 Shiro 中,我们需要自定义一个 CAS Filter,处理 CAS 的登录、验证等流程。可以继承 `org.apache.shiro.cas.CasFilter` 并覆盖相应方法,或者直接使用默认的过滤器配置。 3. **认证与...

    长江养老CAS系统接口开发20101231

    3. **自定义配置**:由于每个组织的安全需求不同,可能需要对CAS服务器进行定制化配置,比如调整登录页面、增加自定义认证模块或扩展服务验证策略。 4. **服务注册**:每个需要接入CAS的业务系统都必须在CAS服务器...

    spring boot 集成kisso单点登入

    编写异常处理器来捕获和处理可能出现的认证、授权错误,如无效的SSO令牌、未登录等情况,确保用户能得到清晰的错误提示。 9. **测试与调试** 对SSO功能进行详尽的测试,包括正常登录、注销、跨应用跳转等场景。...

    java实现可跨浏览器单点登录

    合理的异常处理和错误提示能提升用户体验。 7. **扩展性和可维护性**:设计SSO系统时,应考虑到未来可能的新应用加入或旧应用的移除,因此需保证系统的扩展性和可维护性,如采用模块化设计,使每个组件职责明确。 ...

    java单点登录的实现与应用整合中SSO的技术实现.rar

    4. **异常处理**:处理认证失败、票证过期等各种异常情况,提供友好的错误提示。 总之,Java SSO的实现涉及多个层面,包括协议选择、认证机制、会话管理、安全性设计以及与其他应用的集成。通过合理的设计和实现,...

    spring security2 安全手册(牛人写的)

    - **定义访问拒绝页面**:当用户尝试访问未被授权的资源时,自定义一个友好的提示页面。 #### 7. 动态管理资源结合自定义登录页面 - **结合自定义登录页面**:整合之前创建的自定义登录页面与动态资源管理功能。 ...

    Spring Security3技术手册

    - 当用户尝试访问没有权限的资源时,可以自定义一个页面来提示用户。 - **示例代码**: 在`spring-security.xml`中配置自定义拒绝访问页面。 **8. 动态管理资源结合自定义登录页面** - 结合前两节的知识点,实现...

    springsecurity.pdf

    配置CAS服务器可以选择使用不同的版本(如2.0、3.0等),并根据具体需求进行自定义设置。 ##### 18.4 配置CAS客户端 配置CAS客户端通常涉及到设置CAS服务器地址、服务名称等参数,以便与CAS服务器进行交互。 综上...

    ssm整合shiro

    8. **全局异常处理**:配置全局的Shiro异常处理,如未登录、无权限等,可以统一返回友好的提示信息。 通过以上步骤,我们可以构建一个完整的SSM+Shiro的权限管理系统,实现用户登录、权限控制和会话管理等功能。...

    webform+sso

    Webform + SSO(Single Sign-On)是一种在多个应用程序间实现单点登录的技术,它允许用户在一个应用系统中登录后,无需再次输入凭证即可访问其他相互信任的应用系统。在本项目中,我们使用C#语言和ASP.NET Web Forms...

    sso:java单点登录

    Java SSO(Single Sign-On)单点登录...- **异常处理**:正确处理认证失败、令牌无效等情况,提供友好的错误提示。 通过这个项目,开发者可以掌握SSO的基本原理和实现方式,进一步提升在企业级应用中的身份验证能力。

    考拉开发指南

    - **定义**:描述如何自定义登录验证过程。 - **实例**:给出自定义登录验证的具体实现代码。 - **通配符权限控制** - **定义**:解释如何使用通配符来控制权限。 - **实例**:给出使用通配符控制权限的代码示例...

    内存测试工具rmma38bin

    时序设置对于内存性能至关重要,timings.exe可能是一个工具,用于查看或调整内存的CAS延迟、时钟周期等参数,而timings.dat可能存储了默认或用户自定义的内存时序数据。 5. **RMMT.exe**:可能代表“RMMA内存测试”...

Global site tag (gtag.js) - Google Analytics