Compartir a través de


Flujo de trabajo primero y ejemplo de seguridad

Download sample

Nota

Para generar y ejecutar este ejemplo, es necesario que esté instalado .NET Framework versión 3.5. Para abrir los archivos de solución y proyecto se necesita Visual Studio 2008.

Este ejemplo muestra dos características críticas dentro de los servicios del flujo de trabajo:

  • El método de "Flujo de trabajo primero" de servicios de creación

    Puede crear servicios utilizando los flujos de trabajo de una de las dos maneras. Uno es creación "contrato primero", donde el contrato ya existe y el flujo de trabajo implementa el contrato. El otro es flujo de trabajo primero, que crea el contrato cuando se crea el flujo de trabajo. El Workflow Designer, en vigor, se comporta como el diseñador del contrato. En este ejemplo, el contrato de la calculadora se crea cuando se crea el flujo de trabajo.

    En este ejemplo, la marca para el flujo de trabajo primero se implementa en el archivo SequentialCalculatorService.xoml. Para entender el modelo de programación detrás de la programación del flujo de trabajo primero, compare esto con la marca para obtener otros ejemplos del flujo de trabajo.

    El siguiente código de ejemplo muestra la marca para la actividad Receive en el ejemplo.

    <ns0:ReceiveActivity x:Name="ReceiveAdd" OperationValidation="ValidateOwner" CanCreateInstance="True">
    <ns0:ReceiveActivity.ServiceOperationInfo>
            <ns0:OperationInfo PrincipalPermissionRole="Administrators" Name="Add" ContractName="ICalculator">
                <ns0:OperationInfo.Parameters>
                              <ns0:OperationParameterInfo Attributes="In" ParameterType="{x:Type p15:Int32}" Name="value" Position="0" 
                                       xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
                                       <ns0:OperationParameterInfo Attributes="Out" ParameterType="{x:Type p15:Int32}" Name="returnValue" Position="1" 
                                       xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
                </ns0:OperationInfo.Parameters>
            </ns0:OperationInfo>
    </ns0:ReceiveActivity.ServiceOperationInfo>
        <ns0:ReceiveActivity.ParameterBindings>
            <WorkflowParameterBinding ParameterName="value">
                <WorkflowParameterBinding.Value>
                    <ActivityBind Name="SequentialCalculatorService" Path="inputValue" />
                </WorkflowParameterBinding.Value>
            </WorkflowParameterBinding>
            <WorkflowParameterBinding ParameterName="returnValue">
                <WorkflowParameterBinding.Value>
                    <ActivityBind Name="SequentialCalculatorService" Path="currentValue" />
                </WorkflowParameterBinding.Value>
            </WorkflowParameterBinding>
        </ns0:ReceiveActivity.ParameterBindings>
        <CodeActivity x:Name="DoAdd" ExecuteCode="Add" />
    </ns0:ReceiveActivity>
    

    La actividad Receive no contiene ninguna referencia a un tipo de contrato externo y el contrato se define dentro de la propia actividad Receive. El bloque OperationInfo en la actividad Receive describe el nombre del contrato y el nombre de la operación. Éstas son cadenas literales que no contienen ninguna referencia a un tipo que defina el contrato.

    Al ejecutar el ejemplo, el host de servicio de flujo de trabajo utiliza esta definición para crear una descripción del servicio. Para crear un cliente del servicio para ello, utilice ServiceModel Metadata Utility Tool (Svcutil.exe).

  • Seguridad en servicios del flujo de trabajo

    Los servicios del Flujo de trabajo proporcionan dos niveles de seguridad para su servicio. En el primer nivel especifica la seguridad del permiso del principio en una operación. El servicio en tiempo de ejecución comprueba el permiso antes de entregar el mensaje al flujo de trabajo. Si el mensaje no reúne la seguridad del permiso de principio, el mensaje no se entrega al flujo de trabajo. El segundo nivel es la "condición de validación de la operación", que puede asignar a una actividad Receive. Se ejecuta la condición de validación de operación cuando la actividad Receive recibe el mensaje. Si el mensaje no cumple la condición de validación de operación, se envía al cliente un error, se elimina el mensaje y se critica el flujo de trabajo.

    El atributo PrincipalPermissionRole en el elemento OperationInfo especifica que sólo los usuarios en el grupo Administradores pueden llamar a esta operación.

    El atributo OperationValidation en la actividad Receive señala la ejecución del controlador del código como condición para la validación. En este ejemplo, sólo los usuarios en el grupo Administradores pueden invocar la primera operación, porque el atributo PrincipalPermissionRole se establece en la primera actividad Receive. En este flujo de trabajo, la actividad ReceiveAdd Receive tiene la propiedad CanCreateInstance establecida en true. Esto significa que se crea una instancia de este servicio cuando un usuario llama a la operación Agregar en el grupo Administradores.

    En las operaciones de Receive subsiguientes, la condiciónOperationValidation comprueba para asegurarse de que la entidad de seguridad que invoca la operación es la misma entidad de seguridad que creó la instancia. En este escenario, sólo quien inició la instancia puede enviar más mensajes. El ejemplo siguiente muestra el código en la condición OperationValidation que realiza esta operación.

    private void ValidateOwner(object sender, OperationValidationEventArgs e)
    {
        if (string.IsNullOrEmpty(owner))
        {
            owner = ExtractCallerName(e.ClaimSets);
            e.IsValid = true;
            Console.WriteLine("Owner: " + owner);
        }
        if (owner.Equals(ExtractCallerName(e.ClaimSets)))
            e.IsValid = true;
    }
    private string ExtractCallerName(ReadOnlyCollection<ClaimSet> claimSets)
    {
        string owner = string.Empty;
        foreach (ClaimSet claims in claimSets)
        {
            foreach (Claim claim in claims)
            {
                if (claim.ClaimType.Equals(ClaimTypes.Name) && 
                     claim.Right.Equals(Rights.PossessProperty))
                {
                    owner = claim.Resource.ToString();
                    break;
                }
            }
        }
        return owner;
    }
    

    El método ValidateOwner mostrado proporciona los conjuntos de demandas como parte del argumento OperationValidationEventArgs. Con estos conjuntos de demandas, se completa la validación del mensaje. Observe que en este punto, los parámetros del cuerpo del mensaje reales no están todavía disponibles. El método ExtractCallerName extrae el nombre del llamador del La demanda del nombre y lo almacena. En solicitudes subsiguientes, el nombre del llamador se comprueba con la demanda del nombre del mensaje entrante para comprobar que la misma persona que envió el primer mensaje (y produjo la creación de la instancia) es la misma que envió el mensaje subsiguiente.

Para configurar, generar y ejecutar el proyecto

  1. Realice las instrucciones de instalación en Procedimiento de instalación único para ejemplos de Windows Communication Foundation.

  2. Ejecute el script CreateStores.cmd situado en el tema Procedimiento de instalación único para ejemplos de Windows Communication Foundation.

  3. Genere la solución.

    Ejecute el ejemplo como un usuario desde el grupo Administradores. Primero inicie el ejecutable de servicio, a continuación la aplicación ejecutable del cliente. Si está utilizando Windows Vista, haga clic con el botón secundario en el archivo ejecutable y, a continuación, haga clic en Ejecutar como administrador. El ejemplo se ejecuta hasta su finalización.

    Pruebe a ejecutar el ejemplo mediante una identidad de usuario diferente (utilice un comando de Ejecutar Como para ejecutarse como una identidad diferente). Si la identidad no pertenece al grupo de Administradores, el servicio devuelve un error.

Para ejecutar el ejemplo en equipos independientes

  1. Modifique los archivos de configuración para el servicio y el cliente, asegurándose de que cambia el nombre del servidor en la dirección del extremo. Cambie el nombre del servidor de localhost al nombre de equipo en el que estará ejecutando el servicio.

  2. El servicio utiliza el puerto 8888, por lo cual, debe abrir este puerto en el firewall. En el Panel de control de Windows, haga clic en Firewall de Windows. Haga clic en Agregar puerto y, a continuación, agregue el puerto 8888. De forma alternativa, puede ejecutar el servicio en el puerto predeterminado. Para esto, quite : 8888 de la dirección del extremo

  3. Modifique el archivo de configuración del cliente y agregue el elemento siguiente como un elemento secundario del elemento <endpoint>:

    <identity>
        <UserPrincipalName value=”*@<Domain Name in which your server is running” />
    </identity>
    

    Para determinar el nombre de dominio, inicie el servicio en el equipo en el que piensa ejecutarlo. En una ventana del símbolo del sistema en el otro equipo, ejecute el comando siguiente:

    svcutil.exe http://<serverName>:8888/servicehost/Calculator.svc

    Este comando genera un archivo .cs y un archivo output.config. En el elemento <endpoint> del archivo de configuración, copie el elemento <identity> a su archivo de configuración del cliente.

Footer image

Copyright © 2007 Microsoft Corporation. Reservados todos los derechos.