`

Cas4集成第三方认证登录

 
阅读更多

1:Cas单点登录原理不做具体介绍了,参考百度推荐文章

2:在开发过程中,客户要求登录使用客户开发的身份统一认证中心,统一身份有cas,oauth2,openid等,这里就简单介绍Cas第三方认证中心,应用调用第三方身份中心,如何获取第三方用户信息,回调返回携带参数等问题,这里以Cas4.2去实现该需求:

下面是一个简单流程:

1):应用发起一个登录请求:

        http://localhost:8043/cas/login?service=http://localhost:8002/sgms?center=cas8043

        center参数:代表不同的第三方认证中心code,通过数据库表去查询,跳转至第三方身份认证中心地址进行登录

2:第三方认证中心登录成功,跳转至我们自己的身份中心,此时返回携带第三方ST,并且可以获取第三方用户名,我们用第三方账户用户名,在我们cas作一个自动登录流程,向浏览器写入cookie,tgt,跳转至最初我们发起请求的应用,注:第三方cas跳转至我们cas携带参数,需二次跳转,否则我们cas自动登录成功,跳转应用地址属于失败状态

        具体表设计:

        DROP TABLE IF EXISTS `cas_third_certification_center`;

        CREATE TABLE `cas_third_certification_center` (

       `id` char(32) NOT NULL,

       `code` varchar(64) DEFAULT NULL,

       `url` varchar(255) DEFAULT NULL COMMENT '第三方认证中心地址',

        `create_id` char(32) DEFAULT NULL,

       `create_time` datetime DEFAULT NULL,

       `update_id` char(32) DEFAULT NULL,

       `update_time` datetime DEFAULT NULL,

        PRIMARY KEY (`id`)

        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

         INSERT INTO `cas_third_certification_center` VALUES ('00072e05bf0e4cdaaf1d7d560e11ad11', 'cas8044', 'http://192.168.1.202:8044/cas', null, null, null, null);

         INSERT INTO `cas_third_certification_center` VALUES ('00072e05bf0e4cdaaf1d7d560efbad11', 'cas8043', 'http://192.168.1.202:8043/cas', null, null, null, null);

    

      cas8044=》http://192.168.1.202:8044/cas

      cas8043=》http://192.168.1.202:8043/cas

      

      查看Cas4.2源码,找到切入点,service检测对应serviceAuthorizationCheck,定义class继承该类,或者重新定义bean,这里我重新定义bean,代码如下

@Component("serviceAuthorizationCheckOver")
public final class ServiceAuthorizationCheckOver extends AbstractAction {

    private JdbcTemplate jdbcTemplate;
    private DataSource dataSource;
@Autowired(required = false)
    public void setDataSource(@Qualifier("queryDatabaseDataSource") final DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.dataSource = dataSource;
}

    protected final JdbcTemplate getJdbcTemplate() {
        return this.jdbcTemplate;
}

    protected final DataSource getDataSource() {
        return this.dataSource;
}

    @NotNull
private final ServicesManager servicesManager;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
     * Initialize the component with an instance of the services manager.
     *
     * @param servicesManager the service registry instance.
     */
@Autowired
public ServiceAuthorizationCheckOver(@Qualifier("servicesManager") final ServicesManager servicesManager) {
        this.servicesManager = servicesManager;
}

    @Override
protected Event doExecute(final RequestContext context) throws Exception {
        HttpServletRequest request = WebUtils.getHttpServletRequest(context);
HttpServletResponse response = WebUtils.getHttpServletResponse(context);
// self cas certificate center
String requestUrl = request.getRequestURL().toString();
String returnUrlKey = Constants.SERVICE_KEY;
String centerCodeKey = Constants.CENTER_CODE_KEY;
        final Service service = WebUtils.getService(context);
context.getFlowScope().put("step", "none");
context.getFlowScope().put("rtnParaStr", "");
        if (service == null) {
            return success();
}

        HttpSession session = request.getSession();
String secondRedirect = (String) session.getAttribute("centerCode");
// get service's parameter of center
Map<String, String> serviceQueryParaMap = UrlCodeUtil.urlSplit(service.getId());
        if (serviceQueryParaMap.containsKey(centerCodeKey) && !StringUtils.isEmpty(serviceQueryParaMap.get(centerCodeKey))
                && StringUtils.isEmpty(secondRedirect)) {

            final String centerCode = serviceQueryParaMap.get(centerCodeKey);
            final String returnUrl = context.getRequestParameters().get(returnUrlKey);
CasThirdCertificationCenterDomain thirdCasDO = this.getCertificateInfo(centerCode);
String encodeUrlString = UrlCodeUtil.encoderString(requestUrl + "?" + returnUrlKey + "=" +
                    returnUrl.substring(0, returnUrl.lastIndexOf('?')));
String url = thirdCasDO.getUrl() + "?" + returnUrlKey + "=" + encodeUrlString;
session.setAttribute("centerCode", centerCode);
session.setAttribute("second", false);
// set redirect url
context.getFlowScope().put("url", url);
context.getFlowScope().put("step", "third");
            return success();
}

        if (this.servicesManager.getAllServices().isEmpty()) {
            final String msg = String.format("No service definitions are found in the service manager. "
+ "Service [%s] will not be automatically authorized to request authentication.", service.getId());
logger.warn(msg);
            throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_EMPTY_SVC_MGMR);
}
        // check current service if null or valid
final RegisteredService registeredService = this.servicesManager.findServiceBy(service);
        if (registeredService == null) {
            final String msg = String.format("Service Management: Unauthorized Service Access. "
+ "Service [%s] is not found in service registry.", service.getId());
logger.warn(msg);
            throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);
}
        // service must existed and valid and then second redirect
if (context.getRequestParameters().contains(Constants.CAS_TICKET_KEY)) {
            if (!context.getRequestParameters().contains(returnUrlKey)) {
                final String msg = "Service key not exist.";
logger.warn(msg);
                throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);
}
            String callBackUrl = request.getRequestURL().toString() + "?service=" +
                    context.getRequestParameters().get(returnUrlKey);
String centerCode = (String) session.getAttribute("centerCode");
CasThirdCertificationCenterDomain casDO = this.getCertificateInfo(centerCode);
String ticket = context.getRequestParameters().get(Constants.CAS_TICKET_KEY);
String username = "";
// get user information from third-party
try {
                TicketValidator ticketValidator = new Cas20ServiceTicketValidator(casDO.getUrl());
Assertion casAssertion = ticketValidator.validate(ticket, callBackUrl);
AttributePrincipal casPrincipal = casAssertion.getPrincipal();
username = casPrincipal.getName();
} catch (Exception e) {
                final String msg = String.format("Get username from [%s] failure", casDO.getUrl());
logger.warn(e.getMessage());
                throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);
}
            String url = callBackUrl + "?center" + "=" + session.getAttribute("centerCode");
context.getFlowScope().put("step", "secondRedirect");
session.setAttribute("username", username);
context.getFlowScope().put("secondRedirectUrl", url);
            return success();
}
        // second redirect to local cas center
if (serviceQueryParaMap.containsKey(centerCodeKey) && !StringUtils.isEmpty(serviceQueryParaMap.get(centerCodeKey))
                && !StringUtils.isEmpty(secondRedirect)) {
            String username = (String) session.getAttribute("username");
context.getFlowScope().put("step", "autoSubmit");
context.getFlowScope().put("username", username);
session.invalidate();
            return success();
}
        if (!registeredService.getAccessStrategy().isServiceAccessAllowed()) {
            final String msg = String.format("Service Management: Unauthorized Service Access. "
+ "Service [%s] is not allowed access via the service registry.", service.getId());
logger.warn(msg);
WebUtils.putUnauthorizedRedirectUrlIntoFlowScope(context,
registeredService.getAccessStrategy().getUnauthorizedRedirectUrl());
            throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);
}
        return success();
}

    private CasThirdCertificationCenterDomain getCertificateInfo(String centerCode) throws GeneralSecurityException {
        String searchSqlQuery = "select * from cas_third_certification_center where code = '" + centerCode +
                "' LIMIT 1";
        if (getJdbcTemplate() == null) {
            throw new GeneralSecurityException("Authentication handler is not configured correctly");
}
        CasThirdCertificationCenterDomain thirdCasDO = getJdbcTemplate().queryForObject(searchSqlQuery,
                new CasThirdCertificationCenterRowMapper());
        if (thirdCasDO == null) {
            final String msg = String.format("Third certificate code not correct, can not find third integrated " +
                    "certificate center,the code is [%s].", centerCode);
logger.warn(msg);
            throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);
}
        return thirdCasDO;
}
}

login.workflow代码

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/webflow"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow.xsd">
<!-- 用来存储用户名和密码信息 -->
<var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential"/>
    <on-start>
        <evaluate expression="initialFlowSetupAction"/>
    </on-start>
    <action-state id="ticketGrantingTicketCheck">
        <evaluate expression="ticketGrantingTicketCheckAction"/>
        <transition on="notExists" to="gatewayRequestCheck"/>
        <transition on="invalid" to="terminateSession"/>
        <transition on="valid" to="hasServiceCheck"/>
    </action-state>
    <action-state id="terminateSession">
        <evaluate expression="terminateSessionAction.terminate(flowRequestContext)"/>
        <transition to="gatewayRequestCheck"/>
    </action-state>
    <decision-state id="gatewayRequestCheck">
        <if test="requestParameters.gateway != '' and requestParameters.gateway != null and flowScope.service != null"
then="gatewayServicesManagementCheck" else="serviceAuthorizationCheck"/>
    </decision-state>
    <decision-state id="hasServiceCheck">
        <if test="flowScope.service != null" then="renewRequestCheck" else="viewGenericLoginSuccess"/>
    </decision-state>
    <decision-state id="renewRequestCheck">
        <if test="requestParameters.renew != '' and requestParameters.renew != null" then="serviceAuthorizationCheck"
else="generateServiceTicket"/>
    </decision-state>
<!-- Do a service authorization check early without the need to login first -->
<action-state id="serviceAuthorizationCheck">
        <evaluate expression="serviceAuthorizationCheckOver"/>
        <transition to="ssoCheck"/>
    </action-state>
    <decision-state id="ssoCheck">
        <if test="flowScope.step == 'none'" then="initializeLogin"/>
        <if test="flowScope.step == 'autoSubmit'" then="autoLogin"/>
        <if test="flowScope.step == 'third'" then="redirectThirdSSO"/>
        <if test="flowScope.step == 'secondRedirect'" then="secondRedirect"/>
    </decision-state>
    <end-state id="redirectThirdSSO" view="externalRedirect:#{flowScope.url}"></end-state>
    <end-state id="secondRedirect" view="externalRedirect:#{flowScope.secondRedirectUrl}"></end-state>
    <action-state id="autoLogin">
        <evaluate expression="'success'"/>
        <transition on="success" to="autoLoginNoSubmit"/>
        <transition on="successWithWarnings" to="showMessages"/>
        <transition on="authenticationFailure" to="handleAuthenticationFailure"/>
        <transition on="error" to="initializeLogin"/>
    </action-state>
    <action-state id="autoLoginNoSubmit">
        <evaluate
expression="authenticationViaFormActionOver.autoLoginNoSubmit(flowRequestContext, messageContext,
                flowScope.username)"/>
        <transition on="success" to="sendTicketGrantingTicket"/>
    </action-state>
<!--
        The "warn" action makes the determination of whether to redirect directly to the requested
        service or display the "confirmation" page to go back to the server.
    -->
<decision-state id="warn">
        <if test="flowScope.warnCookieValue" then="showWarningView" else="redirect"/>
    </decision-state>
    <action-state id="initializeLogin">
        <evaluate expression="'success'"/>
        <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"/>
<!--
            <binding property="rememberMe" />
            -->
</binder>
        <on-entry>
            <set name="viewScope.commandName" value="'credential'"/>
<!--
            <evaluate expression="samlMetadataUIParserAction" />
            -->
</on-entry>
        <transition on="submit" bind="true" validate="true" to="realSubmit"/>
    </view-state>
    <action-state id="realSubmit">
        <evaluate
expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.credential, messageContext)"/>
        <transition on="warn" to="warn"/>
<!--
        To enable AUP workflows, replace the 'success' transition with the following:
        <transition on="success" to="acceptableUsagePolicyCheck" />
        -->
<transition on="success" to="loginSuccess"/>
        <transition on="successWithWarnings" to="showMessages"/>
        <transition on="authenticationFailure" to="handleAuthenticationFailure"/>
        <transition on="error" to="initializeLogin"/>
    </action-state>
    <action-state id="loginSuccess">
        <evaluate expression="loginSuccessAction"/>
        <transition on="success" to="sendTicketGrantingTicket"/>
    </action-state>
    <view-state id="showMessages" view="casLoginMessageView">
        <on-entry>
            <evaluate expression="sendTicketGrantingTicketAction"/>
            <set name="requestScope.messages" value="messageContext.allMessages"/>
        </on-entry>
        <transition on="proceed" to="serviceCheck"/>
    </view-state>
    <action-state id="handleAuthenticationFailure">
        <evaluate expression="authenticationExceptionHandler.handle(currentEvent.attributes.error, messageContext)"/>
        <transition on="AccountDisabledException" to="casAccountDisabledView"/>
        <transition on="AccountLockedException" to="casAccountLockedView"/>
        <transition on="AccountPasswordMustChangeException" to="casMustChangePassView"/>
        <transition on="CredentialExpiredException" to="casExpiredPassView"/>
        <transition on="InvalidLoginLocationException" to="casBadWorkstationView"/>
        <transition on="InvalidLoginTimeException" to="casBadHoursView"/>
        <transition on="FailedLoginException" to="errorCount"/>
        <transition on="AccountNotFoundException" to="initializeLogin"/>
        <transition on="UNKNOWN" to="initializeLogin"/>
    </action-state>
    <action-state id="errorCount">
        <evaluate expression="repeatLoginErrorCountAction"/>
        <transition on="success" to="initializeLogin"/>
    </action-state>
    <action-state id="sendTicketGrantingTicket">
        <evaluate expression="sendTicketGrantingTicketAction"/>
        <transition to="serviceCheck"/>
    </action-state>
    <decision-state id="serviceCheck">
        <if test="flowScope.service != null" then="generateServiceTicket" else="viewGenericLoginSuccess"/>
    </decision-state>
    <action-state id="generateServiceTicket">
        <evaluate expression="generateServiceTicketAction"/>
        <transition on="success" to="warn"/>
        <transition on="authenticationFailure" to="handleAuthenticationFailure"/>
        <transition on="error" to="initializeLogin"/>
        <transition on="gateway" to="gatewayServicesManagementCheck"/>
    </action-state>
    <action-state id="gatewayServicesManagementCheck">
        <evaluate expression="gatewayServicesManagementCheck"/>
        <transition on="success" to="redirect"/>
    </action-state>
    <action-state id="redirect">
        <evaluate expression="flowScope.service.getResponse(requestScope.serviceTicketId)"
result-type="org.jasig.cas.authentication.principal.Response" result="requestScope.response"/>
        <transition to="postRedirectDecision"/>
    </action-state>
    <decision-state id="postRedirectDecision">
        <if test="requestScope.response.responseType.name() == 'POST'" then="postView" else="redirectView"/>
    </decision-state>
<!--
        the "viewGenericLoginSuccess" is the end state for when a user attempts to login without coming directly from a service.
        They have only initialized their single-sign on session.
    -->
    <!--    <end-state id="viewGenericLoginSuccess" view="externalRedirect:#{flowScope.credential.sys_url}" />-->
<end-state id="viewGenericLoginSuccess" view="casGenericSuccessView">
        <on-entry>
            <evaluate expression="genericSuccessViewAction.getAuthenticationPrincipal(flowScope.ticketGrantingTicketId)"
result="requestScope.principal"
result-type="org.jasig.cas.authentication.principal.Principal"/>
        </on-entry>
    </end-state>
<!--
    The "showWarningView" end state is the end state for when the user has requested privacy settings (to be "warned")
    to be turned on.  It delegates to a view defines in default_views.properties that display the
    "Please click here to go to the service." message.
    -->
<end-state id="showWarningView" view="casConfirmView"/>
<!-- Password policy failure states -->
<end-state id="abstactPasswordChangeView">
        <on-entry>
            <set name="flowScope.passwordPolicyUrl" value="passwordPolicyConfiguration.passwordPolicyUrl"/>
        </on-entry>
    </end-state>
    <end-state id="casExpiredPassView" view="casExpiredPassView" parent="#abstactPasswordChangeView"/>
    <end-state id="casMustChangePassView" view="casMustChangePassView" parent="#abstactPasswordChangeView"/>
    <end-state id="casAccountDisabledView" view="casAccountDisabledView"/>
    <end-state id="casAccountLockedView" view="casAccountLockedView"/>
    <end-state id="casBadHoursView" view="casBadHoursView"/>
    <end-state id="casBadWorkstationView" view="casBadWorkstationView"/>
    <end-state id="postView" view="postResponseView">
        <on-entry>
            <set name="requestScope.parameters" value="requestScope.response.attributes"/>
            <set name="requestScope.originalUrl" value="flowScope.service.id"/>
        </on-entry>
    </end-state>
<!--
        The "redirect" end state allows CAS to properly end the workflow while still redirecting
        the user back to the service required.
    -->
<end-state id="redirectView" view="externalRedirect:#{requestScope.response.url}#{flowScope.rtnParaStr}"/>
    <end-state id="viewServiceErrorView" view="serviceErrorView"/>
    <decision-state id="serviceUnauthorizedCheck">
        <if test="flowScope.unauthorizedRedirectUrl != null"
then="viewRedirectToUnauthorizedUrlView"
else="viewServiceErrorView"/>
    </decision-state>
    <end-state id="viewRedirectToUnauthorizedUrlView" view="externalRedirect:#{flowScope.unauthorizedRedirectUrl}"/>
    <end-state id="viewServiceSsoErrorView" view="serviceErrorSsoView"/>
    <global-transitions>
        <transition to="viewLoginForm" on-exception="org.jasig.cas.services.UnauthorizedSsoServiceException"/>
        <transition to="viewServiceErrorView"
on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException"/>
        <transition to="serviceUnauthorizedCheck" on-exception="org.jasig.cas.services.UnauthorizedServiceException"/>
        <transition to="serviceUnauthorizedCheck"
on-exception="org.jasig.cas.services.UnauthorizedServiceForPrincipalException"/>
    </global-transitions>
</flow>

  

 自动登录,绕过数据库验证,生成tgt,重新定义bean,authenticationViaFormAction

 @Component("authenticationViaFormActionOver")

public class AuthenticationViaFormActionOver {
    /**
     * Authentication succeeded with warnings from authn subsystem that should be displayed to user.
     */
public static final String SUCCESS_WITH_WARNINGS = "successWithWarnings";
/**
     * Authentication failure result.
     */
public static final String AUTHENTICATION_FAILURE = "authenticationFailure";
/**
     * Flow scope attribute that determines if authn is happening at a public workstation.
     */
public static final String PUBLIC_WORKSTATION_ATTRIBUTE = "publicWorkstation";
/**
     * Logger instance.
     **/
protected final transient Logger logger = LoggerFactory.getLogger(getClass());
/**
     * Core we delegate to for handling all ticket related tasks.
     */
@NotNull
    @Autowired
    @Qualifier("centralAuthenticationService")
    private CentralAuthenticationService centralAuthenticationService;
@NotNull
    @Autowired
    @Qualifier("warnCookieGenerator")
    private CookieGenerator warnCookieGenerator;
@NotNull
    @Autowired(required = false)
    @Qualifier("defaultAuthenticationSystemSupport")
    private AuthenticationSystemSupport authenticationSystemSupport = new DefaultAuthenticationSystemSupport();
    public final Event autoLoginNoSubmit(final RequestContext context, final MessageContext messageContext,
                                         final String username) {
        Credential credential = new UsernamePasswordCredential(username, Constants.RANDOM_THIRD_PASSWORD);
        return createTicketGrantingTicket(context, credential, messageContext);
}

    /**
     * Is request asking for service ticket?
     *
     * @param context the context
     * @return true, if both service and tgt are found, and the request is not asking to renew.
     * @since 4.1.0
     */
protected boolean isRequestAskingForServiceTicket(final RequestContext context) {
        final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
        final Service service = WebUtils.getService(context);
        return (StringUtils.isNotBlank(context.getRequestParameters().get(CasProtocolConstants.PARAMETER_RENEW))
                && ticketGrantingTicketId != null
&& service != null);
}

/**
     * Create ticket granting ticket for the given credentials.
     * Adds all warnings into the message context.
     *
     * @param context        the context
     * @param credential     the credential
     * @param messageContext the message context
     * @return the resulting event.
     * @since 4.1.0
     */
protected Event createTicketGrantingTicket(final RequestContext context, final Credential credential,
                                               final MessageContext messageContext) {
        try {
            // 获取service
final Service service = WebUtils.getService(context);
            final AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(
                    this.authenticationSystemSupport.getPrincipalElectionStrategy());
//form表单提交信息封装认证信息
final AuthenticationTransaction transaction = AuthenticationTransaction.wrap(credential);
//进行登录的用户登录名和密码的校验
this.authenticationSystemSupport.getAuthenticationTransactionManager().handle(transaction, builder);
//通过认证信息和service形成认证结果集
final AuthenticationContext authenticationContext = builder.build(service);
//认证成功后进行TGT的创建工作
final TicketGrantingTicket tgt = this.centralAuthenticationService.createTicketGrantingTicket(authenticationContext);
WebUtils.putTicketGrantingTicketInScopes(context, tgt);
WebUtils.putWarnCookieIfRequestParameterPresent(this.warnCookieGenerator, context);
putPublicWorkstationToFlowIfRequestParameterPresent(context);
//如果只是进行服务端代码分析,此处不进行警告
if (addWarningMessagesToMessageContextIfNeeded(tgt, messageContext)) {
                return newEvent(SUCCESS_WITH_WARNINGS);
}
            return newEvent("success");
} catch (final AuthenticationException e) {
            logger.debug(e.getMessage(), e);
            return newEvent(AUTHENTICATION_FAILURE, e);
} catch (final Exception e) {
            logger.debug(e.getMessage(), e);
            return newEvent("error", e);
}
    }

 未完待续,需重新整理

分享到:
评论

相关推荐

    cas3.5.0集成oauth2.0协议

    cas3.5.0集成oauth2.0协议,模拟cas3.5.0通过oauth2.0协议与集成了coauth2.0的cas进行模拟通信。可以实现 与新浪微博等第三方身份验证平台对接,实现单点登录。

    统一身份认证对外文档

    cas统一认证对外集成文档,适用于其他第三方公司使用。

    【MaxKey单点登录认证系统 v2.4.0 RC】企业级IAM身份管理和身份认证产品+RBAC权限管理.zip

    3、提供标准的认证接口以便于其他应用集成SSO,安全的移动接入,安全的API、第三方认证和互联网认证的整合。 4、提供用户生命周期管理,支持SCIM 2协议,基于Apache Kafka代理,通过连接器(Connector)实现身份供给...

    django-spms:django-spms是一个基于Django + AdminLTE的框架,集成了RBAC权限管理,账户管理, JWT认证, 多站点统一登录CAS,基于DRF的API等模块,并集成第三方Celery,pycharts, ckeditor,mdeditor模块,拥有清晰良好的代码结构,有助于快速的开启一个新的项目

    JWT认证, 多站点统一登录CAS,基于DRF的API等模块,并集成第三方Celery,pycharts, ckeditor,mdeditor模块,拥有清晰良好的代码结构,有助于快速的开启一个新的项目。 一、安装 只支持Django 2.2.x, Python 3.6 ...

    weibo oauth 认证jar包

    weibo oauth 认证jar包 cas应用weibo集成

    MaxKey单点登录认证系统-其他

    3、提供标准的认证接口以便于其他应用集成SSO,安全的移动接入,安全的API、第三方认证和互联网认证的整合。 4、提供用户生命周期管理,支持SCIM 2协议,基于Apache Kafka代理,通过连接器(Connector)实现身份供给...

    sso:cas单点登录系统,其中包括cas认证服务,配置中心,监控平台,服务管理的高可用项目

    第三方登录接收(QQ,微信,CSDN,GitHub) 绑定用户 验证码输出 自定义校验器 多属性返回 验证码发送,校验(注册发送邮箱验证码) 服务监控检测 校验码登录 单用户登录 教程: 域名:localhost 用户: 用户名 密码...

    统一用户中心详细设计方案.pdf

    提供平台登录界面; ...提供第三方应用接入相关接口; 提供用户、组织机构、权限相关接口; 提供提醒消息服务的集成, 允许业务子系统存储提醒消息, 以及同步业务子系统自有消 息模块中的消息

    java开源包4

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    矿山多源安全管理系统设计与实现 (2013年)

    针对风险管理、设备安全管理、职业卫生管理等模块中涉及的异构系统数据集成问题,运用第三方信息流模型,将系统划分为数据物理存储层、数据逻辑存储层、应用层、控制层及用户层,设计了系统框架,并重点研究了框架中...

    java开源包1

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包11

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包2

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包3

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包6

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包5

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包10

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包8

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包7

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

    java开源包9

    同时,任何第三方都可以使用OAUTH认证服务,任 何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间...

Global site tag (gtag.js) - Google Analytics