Services d’application

[SP2013] – Accéder aux données du Secure Store Service en C#

Posted on Updated on

Bonjour à tous,

Aujourd’hui un article technique pour vous montrer comment accéder aux données stockées dans le Secure Store Service de SharePoint Server 2013.

A quoi sert ce service ? Il suffit de suivre le lien : https://technet.microsoft.com/fr-fr/library/Ee806866.aspx

1/ Contexte général

Le but étant de stocker des données de type login, mot de passe, domaine, Pin, etc. afin d’accéder à des systèmes externe à SharePoint.

Habituellement, on utilise le Secure Store Service (SSS) de SharePoint pour enregistrer les credentials utilisés pour la mise en œuvre de listes externes dans SharePoint par le biais du Business Connectivity Service (BCS, ex-BDC). imaginons le cas où l’on souhaite afficher dans SharePoint une base de clients/fournisseurs qui provient d’une base de données SQL Server. Cette base peut utiliser un mode d’authentification SQL (et non Annuaire AD) et il faut donc envoyer un login/mot de passe pour pouvoir se connecter et requêter la base depuis SharePoint. C’est donc un SSO (Single Sign-On) mais Inter-Domaine (Cross-Domain) que nous propose Microsoft. Les données de cette base d’identifiants sont chiffrées via une clé générée par SharePoint lui-même (à partir d’une phrase secrète qu’il ne faut pas perdre !).

Dans le cas présent, le but est d’accéder à ce Secure Store Service afin de stocker, lire, mettre à jour les données d’un utilisateur, et proposer par exemple un formulaire de connexion, de mise à jour de ces données directement depuis un portail SharePoint.

2/ Architecture du service

Le Secure Store Service est une Application de Service proposée par SharePoint Server 2013 (Standard ou Enterprise). Elle peut se déployer par la console d’administration centrale ou PowerShell (voir l’article Technet précédent).

La clé de chiffrement permet de chiffrer les données stockées dans la base de données associée à l’application de service.

Les données sont stockées dans des Target Applications (Applications cibles). Chaque Target application stocke les données pour 1 application, par exemple :

  • Une Target Application pour la connexion à une base SQL Server
  • Une Target Application pour la connexion à une ferme Dynamics CRM
  • Une Target Application pour la connexion à SAP
  • Une Target Application pour la connexion à une base Oracle

Chacune de ces Target Application est définie par l’administrateur SharePoint où il doit fournir :

  1. ID de l’application cible : identifiant unique de la Target Application
  2. Nom complet : nom d’affichage de la Target Application
  3. Messagerie de contact : adresse e-mail de contact pour l’administrateur de cette Target Application
  4. Url de la page d’application cible : voir article Technet
  5. Type d’application cible : il s’agit ici d’indiquer si chaque utilisateur aura sa propre identification ou si l’on va définir une identification pour tout un groupe de personnes (individual ou group).

Ensuite vous devrez spécifier les champs que vous souhaitez enregistrer : champs d’identification Windows, champs d’identification standards (login/mot de passe), code Pin, domaine, etc.

Et enfin les administrateurs de la Target Application. Bref, tout cela est plutôt bien défini dans l’article Technet.

3/ Lire des credentials depuis mon code en C#

Voici enfin le cœur du problème. Comment accéder aux données stockées dans le SSS depuis mon code ?

J’ai tout d’abord défini une classe métier pour stocker quelques informations : Login, password, Login SharePoint, Nom Complet et E-mail de l’utilisateur :


namespace MonDev.LogMe.Utils
{
   public class SSSCredentials
   {
      public string Login { get; set; }
      public string Password { get; set; }
      public string SPLogin { get; set; }
      public string SPFullName { get; set; }
      public string SPEmail { get; set; }
   }
}

Ensuite, voici le code de la méthode GetCredentials que j’utilise. Les paramètres attendus sont :

  • site : collection de sites courante
  • applicationID : identifiant (interne) de la Target Application

   /// Get credentials for current connected user from Secure Store Service.
   /// current site collection, associated to a Secure Store Service at Web Application Level
   /// Target Application ID in Secure Store Service
   /// Returns Credentials if found, null otherwise.
   public static SSSCredentials GetCredentials(SPSite site, string applicationID)
   {
      //Initialize new Credentials structure
      SSSCredentials credentials = new SSSCredentials();
      credentials.SPEmail = site.RootWeb.CurrentUser.Email;
      credentials.SPFullName = !string.IsNullOrEmpty(site.RootWeb.CurrentUser.Name) ? site.RootWeb.CurrentUser.Name : site.RootWeb.CurrentUser.LoginName;
      credentials.SPLogin = site.RootWeb.CurrentUser.LoginName;

      //new SPSite is not mandatory, but it seems to be more efficient than use SPSite from parameters.
      using (SPSite currentSite = new SPSite(site.ID))
      {
         //Initialize a new SecureProvider to access to data into SSS
         ISecureStoreProvider provider = SecureStoreProviderFactory.Create();
         if (provider == null)
            throw new InvalidOperationException("Unable to get an ISecureStoreProvider");

         ISecureStoreServiceContext providerContext = provider as ISecureStoreServiceContext;
         providerContext.Context = SPServiceContext.GetContext(currentSite);

         try
         {
            using (SecureStoreCredentialCollection creds = provider.GetCredentials(applicationID))
            {
               if (creds != null)
               {
                  foreach (SecureStoreCredential cred in creds)
                  {
                     if (cred == null)
                        continue;

                     switch (cred.CredentialType)
                     {
                        case SecureStoreCredentialType.UserName:
                           credentials.Login = GetStringFromSecureString(cred.Credential);
                           break;
                        case SecureStoreCredentialType.Password:
                           credentials.Password = GetStringFromSecureString(cred.Credential);
                           break;
                        default:
                           break;
                     }
                  }
               }
            }
         }
         catch (SecureStoreException)
         {
            //No credentials are found into SSS, so return null
            return null;
         }
         catch (Exception e)
         {
            throw new Exception("A general error occured. Please contact your administrator. Error : " + e.Message);
         }
      }
      return credentials;
   }

La méthode doit être appelée comme suit :


private const string TargetApplicationID = "MaTargetApplication";
SSSCredentials credentials = SSSUtils.GetCredentials(SPContext.Current.Site, TargetApplicationID);

Rien de très compliqué toutefois je suis tombé sur quelques exemples de codes et aucun n’a fonctionné chez moi. A noter ici, pas besoin d’impersonation ou de SPSecurity.RunWithElevatedPrivileges(), bien au contraire. Il faut se connecter au provider avec les identifiants de l’utilisateur connecté au portail pour pouvoir récupérer ses identifiants !

 

4/ Ecrire dans le Secure Store Service

Si nous avons lu, il faut bien parvenir à écrire dans le SSS. Ici la méthode est la même pour l’ajout ou la modification de credentials dans le magasin du Secure Store Service. Les paramètres attendus sont :

  • site : collection de sites courante
  • applicationID : identifiant unique (interne) de la Target Application
  • windowslogin : login Windows ou identifiant de l’utilisateur dans le portail SharePoint
  • userName : nom d’utilisateur à stocker dans le Secure Store Service, dans la Target Application
  • userPassword : mot de passe à stocker dans le Secure Store Service, dans la Target Application

 


public static void SetCredentials(SPSite site, string applicationID, string windowslogin, string userName, string userPassword)
   {
      SPClaim claim = SPClaimProviderManager.CreateUserClaim(windowslogin, SPOriginalIssuerType.Windows);
      SecureStoreServiceClaim ssClaim = new SecureStoreServiceClaim(claim);

      SPServiceContext context = SPServiceContext.GetContext(SPServiceApplicationProxyGroup.Default, SPSiteSubscriptionIdentifier.Default);

      SecureStoreServiceProxy ssp = new SecureStoreServiceProxy();
      ISecureStore iss = ssp.GetSecureStore(context);

      IList applicationFields = iss.GetUserApplicationFields(applicationID);

      IList creds = new List(applicationFields.Count);

      using (SecureStoreCredentialCollection credentials = new SecureStoreCredentialCollection(creds))
      {
         foreach (TargetApplicationField field in applicationFields)
         {
            switch (field.CredentialType)
            {
               case SecureStoreCredentialType.UserName:
                  creds.Add(new SecureStoreCredential(GetSecureStringFromString(userName), SecureStoreCredentialType.UserName));
                  break;
               case SecureStoreCredentialType.Password:
                  creds.Add(new SecureStoreCredential(GetSecureStringFromString(userPassword), SecureStoreCredentialType.Password));
                  break;
               default:
                  break;
            }
         }
         iss.SetCredentials(applicationID, credentials);
      }
   }

La méthode doit être appelée comme suit :


SSSUtils.SetCredentials(SPContext.Current.Site, TargetApplicationID, SPContext.Current.Site.RootWeb.CurrentUser.LoginName, "LOGIN_A_STOCKER", "PASSWORD_A_STOCKER");

A savoir, il est important d’exécuter le code avec le compte de l’utilisateur connecté à SharePoint afin de pouvoir lire ses credentials ou écrire/mettre à jour ses credentials. Lorsque j’essayais d’écrire le code pour faire ces manipulations, je suis tombé sur pas mal de bouts de code où ils essayaient d’exécuter cela avec le compte système via de l’impersonation ou bien SPSecurity.RunWithElevatedPrivileges(). Cela n’a pas marché pour moi !

5/ Fonctions annexes

Dans les extraits de codes précédents, j’ai utilisé quelques méthodes supplémentaire pour encoder/décoder les chaines de caractères envoyées ou reçues depuis le Secure Store Service. Pour être totalement complet, les voici.

Cette première méthode permet de décoder une chaine encodée (SecureString) dans une chaine standard (String)


internal static string GetStringFromSecureString(SecureString secStr)
{
   if (secStr == null)
      return null;

   IntPtr pPlainText = IntPtr.Zero;
   try
   {
      pPlainText = Marshal.SecureStringToBSTR(secStr);
      return Marshal.PtrToStringBSTR(pPlainText);
   }
   finally
   {
      if (pPlainText != IntPtr.Zero)
         Marshal.FreeBSTR(pPlainText);
   }
}

Et bien sûr la méthode effectuant la manipulation inverse :


internal static SecureString GetSecureStringFromString(string str)
{
   if (str == null)
      return null;
   var str2 = new SecureString();
   char[] chArray = str.ToCharArray();
   for (int i = 0; i < chArray.Length; i++)
   {
      str2.AppendChar(chArray[i]);
      chArray[i] = '0';
   }
   return str2;
}

6/ Usings…

J’ai un peu oublié d’en parler au début, mais certains peuvent avoir des difficultés pour inclure les bonnes références et using nécessaires au projet (je ne parlerai pas des assemblies standards…).

Références :

  1. Microsoft.BusinessData (à aller cherche dans) : C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.BusinessData.dll
  2. Microsoft.Office.SecureStoreService (à aller rechercher dans le GAC) : C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.Office.SecureStoreService\v4.0_15.0.0.0__71e9bce111e9429c\Microsoft.Office.SecureStoreService.dll
  3. Microsoft.Office.SecureStoreService.Server.Security (à aller cherche dans) : C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.Office.SecureStoreService.Server.Security.dll

Il ne nous reste plus qu’à trouver un usage à tout ceci ! 🙂

Florent.

[SP2013] – Déployer le Machine Translation Service de SharePoint Server 2013

Posted on Updated on

Bonjour à tous.

Dans cet article je vais tenter de vous expliquer ce qu’est le Machine Translation Service de SharePoint Server 2013 mais également comment le déployer sur votre ferme SharePoint.

J’ai choisi de déployer et configurer un maximum de choses avec PowerShell dans le but d’automatiser le déploiement.

1/ Machine Translation Service : qu’est-ce que c’est ?

Le Machine Translation Service est une nouvelle application de service, apparue avec SharePoint 2013 et disponible dans les versions Standard et Enterprise.

Il permet de traduire automatiquement non seulement les sites (colonnes, listes, pages) mais également le contenu des documents qui seront stockés dans ce site, et ce à la demande des utilisateurs. D’ailleurs ce contenu peut être pré-traduit (via une planification et un TimerJob) ou bien à la volée sur la demande d’un utilisateur.

On comprendra rapidement l’intérêt de ce service lors du déploiement de portails de publication SharePoint utilisant les Variantes.

Plutôt intéressant sur le principe !

Vous trouverez également sur Technet quelques exemple d’appels à API du Machine Translation Service via du code client ou serveur : http://msdn.microsoft.com/fr-fr/library/office/jj163145(v=office.15).aspx.

De plus, ce service limite la taille des fichiers qui pourront être convertis :

Type de fichier / extensions Limite de taille (en Ko)
Texte (txt) 15 360
HTML (html, xhtml, xhtm, htm, aspx) 15 360
Word (doc, docx, docm, dot, dotx, dotm, rtf) 524 288
XLIFF (xlf) 15 360

2/ Prérequis avant le déploiement

Le déploiement de ce service impose quelques prérequis qu’il vous faudra valider ou mettre en œuvre au préalable.

A. Application de service : Gestion des applications

Effectivement, cette application de service Gestion des applications ‘'(App Management Service Application) doit être déployée et configurée sur votre ferme. Pour cela, je vous invite à suivre le guide de déploiement sur Technet : http://technet.microsoft.com/fr-fr/library/fp161236(v=office.15).aspx

B. Application de service : SharePoint Token Service

Le service d’authentification serveur à serveur (STS) doit être déployé et configuré dans le cas où vous travaillez sur une architecture Multi-Tenant. Pour cela, je vous invite à suite le guide de déploiement sur Technet : http://technet.microsoft.com/fr-fr/library/jj655400(v=office.15).aspx

C. Application de service : User Profile

Peut-être un peu plus étonnant, votre ferme doit avoir le Proxy de l’application de service User Profile déployé sur votre ferme SharePoint, et l’application de service correspondante doit être déployée, configurée et démarrée. Pour cela, je vous invite à suivre le guide de déploiement sur Technet : http://technet.microsoft.com/fr-fr/library/ee721052(v=office.15).aspx

D. Accès à internet

Evidemment, ce n’est pas SharePoint qui va effectuer les traductions demandées par les utilisateurs mais bien envoyées et traduites par Microsoft Translation Service. Et donc pour cela, une connexion Internet sur les serveurs SharePoint est requise (ceux où le service de traduction est démarré).

E. Compte de déploiement du service

Evidemment, pour pouvoir déployer et configurer le service, il faut avoir suffisamment de droits. Dans mon cas j’utilise le compte système (compte d’installation de la ferme SharePoint).

De manière générale, ce compte doit avoir les droits :

  • securityadmin sur l’instance SQL Server de votre ferme SharePoint
  • db_owner sur l’instance SQL Server de votre ferme SharePoint
  • Dans le groupe Administrateurs local de vos serveurs SharePoint où on lancera le déploiement

F. Compte du pool d’application

Dans l’exemple que je vais développer ci-après, j’utilise un nouveau pool d’application pour ce service. Il est nécessaire que le compte utilisé par ce pool ait accès au service User Profile avec le contrôle total. Pour cela, il faut se rendre dans la page de gestion du service de profil utilisateur dans la central admin et ajouter le compte avec contrôle total :

12

3/ Déploiement du service avec PowerShell

Ma ferme SharePoint est simple, elle est composée :

  • D’un serveur Controleur de Domaine (AD, windows server 2008R2 + DNS)
  • D’un serveur SharePoint Server 2013 Enterprise EN (+ language pack FR) sans SP1 (Windows Server 2012)

Voici les applications de service déployées sur ma ferme :

02

Une fois les prérequis vérifiés, nous pouvons lancer le SharePoint Management Shell en s’étant au préalable loggé sur le serveur avec le compte qui a les bons droits :

01

Nous allons commencer par créer un nouvel application pool (possible d’utiliser un existant)  et positionner les variables utiles :

#Variables
$servicename = "Machine Translation Service"
$serviceproxyname = $servicename + " Proxy"
$databasename = "SharePoint_MTS"
$databaseserver = "SP2013\SQL2012"
$apppoolname = "SharePoint_MTS_AppPool"
$apppoolaccount = "demo\spappservice"

$apppool = New-SPServiceApplicationPool -Name $apppoolname -Account $apppoolaccount

03

NB : (source Technet) Le compte utilisé par le pool d’applications doit également disposer d’autorisations de contrôle total sur l’application de service de profil utilisateur. Si vous créez un pool d’applications et un compte, veillez à ajouter le compte à la liste des comptes qui peuvent utiliser l’application de service de profil utilisateur, puis accordez les autorisations de contrôle total à ce compte. Pour plus d’informations, voir Limiter ou activer l’accès à une application de service (SharePoint 2013).

Puis l’on va créer l’application de service avec la commande :

New-SPTranslationServiceApplication -Name $servicename -DatabaseName $databasename -DatabaseServer $databaseserver -ApplicationPool $apppoolname –Default

04

05

L’application de service est maintenant créée, il faut démarrer le service sur le serveur :

Get-SPServiceInstance | where-object {$_.TypeName -eq "Machine Translation Service"} | Start-SPServiceInstance

06

07

4/ Configuration du service avec PowerShell

L’application de service étant créée, nous pouvons maintenant la configurer avec PowerShell.

Pour cela, toujours dans le SharePoint Management Shell, nous allons fixer :

  • La fréquence d’exécution du TimerJob de traduction : 15min
  • Le nombre maximal d’essais pour la traduction : 5
  • Le nombre de jours de conservation des travaux de traduction terminés (historique) : 30
  • Le nombre maximal de demandes de traductions synchrones : 100
  • Le nombre maximal de documents à convertir avant le redémarrage de la conversion : 300

Pour cela, nous allons utiliser la commande suivante :

Set-SPTranslationServiceApplication -Identity $servicename -EnableAllFileExtensions -UseDefaultlnternetSettings -TimerJobFrequency 15 -MaximumTranslationAttempts 5 -JobExpirationDays 30 -MaximumSyncTranslationRequests 100 -RecycleProcessThreshold 300 -DisableBinaryFileScan 1

08

Notez bien qu’il faut redémarrer le service juste après, comme précisé dans le Management Shell. Et donc :

Get-SPServiceInstance | where-object {$_.TypeName -eq "Machine Translation Service"} | Stop-SPServiceInstance

Get-SPServiceInstance | where-object {$_.TypeName -eq "Machine Translation Service"} | Start-SPServiceInstance

09

Les paramètres sont bien appliqués dans les paramètres de l’application de service :

10

11

Voilà, c’est bon pour la configuration !

5/ Vérification de la traduction

Pour vérifier le bon fonctionnement de tout cela, j’ai créé une nouvelle collection de sites de type Publishing portal, en Anglais :

13

Sur la page d’accueil du site, on propose directement un lien “Make your site multilingual”. Nous allons pouvoir créer les variantes et leurs étiquettes directement depuis cette page (ou depuis les paramètres du site). Je définis donc une variante par défaut en anglais et une en français :

14

Lors de la création du label français, on propose d’utiliser les service du Machine Translation Service : 15

16

17

Lorsque les étiquettes de variations sont créées, il faut patienter quelques minutes afin que le TimerJob qui créée les hiérarchies soit exécuté. Pour forcer la chose, il vous suffira de lancer ce job manuellement depuis la console d’administration centrale de SharePoint, dans la section “Monitoring” > “Review job definitions” et de trouver le job appelé “Variations Create Hierarchies Job Definition” associé à la WebApplication sur laquelle le portail de publication est créé. Puis de cliquer sur le bouton “Run Now”.

Les variations sont maintenant créées :

18

Et nous pouvons maintenant aller sur les deux variations EN / FR :

19

20

Dans le ruban, dans l’onglet VARIANTES, on a maintenant le bouton “Traduire automatiquement” :

21

 

Un message apparait nous informant que quelques configurations sont encore nécessaires et nous seront notifiés par e-mail :22

A noter au passage que la traduction n’est pas possible depuis le site anglais, puisque c’est la variation “maitre” (pas d’onglet VARIANTES) :

23

Vous pouvez également suivre l’avancement de la traduction via le bouton “Etat de la traduction” dans l’onglet VARIANTES

24

 

Et avec des documents ?  Je me rends donc sur le site Français et j’upload dans la bibliothèque de documents Documents un fichier Word (docx) contenant la recette du cheesecake en anglais. Ce fichier s’appelle cheesecake.docx, et volontairement j’utilise un compte collaborateur sur ma collection de sites appelé “Lenny” :

29

25

A noter la présence du champ “Etat de la traduction” qui est par défaut à la valeur “Traduction effectuée”. J’ai modifié la valeur pour mettre “Traduction demandée”. Pour autant la traduction ne sera pas lancée automatiquement.

Je sélectionne alors l’élément et je clique sur VARIANTES dans le ruban, et je clique sur Traduire automatiquement > Elements sélectionnés uniquement :

26

La traduction démarre :

27

La traduction est terminée, le champ Etat de la traduction est maintenant à la valeur “Traduction effectuée” :

28

Ouvrons le fichier pour voir ce qu’il en est ! Le fichier est “bien” traduit. En effet, cela ne vaudra jamais une belle traduction littéraire, mais cela dit ça reste compréhensible :

30

Vous pouvez également suivre l’état d’avancement de la traduction en utilisant le bouton “Etant de la traduction” dans l’onglet VARIANTES :

31

32

 

Voilà, c’est tout pour aujourd’hui !

[SP2010 – SP2013] – Stocker des données de configuration

Posted on Updated on

Bonjour à tous,

Lorsque nous développons des applications pour SharePoint, il nous arrive bien souvent de vouloir sauvegarder des données de configuration. Ces données peuvent être de simples valeurs (texte, nombre, heure, timestamp, URL, etc.) mais également des données plus complexes comme des objets métiers.

SharePoint 2010 et 2013 (et 2007) nous offrent un certain nombre de possibilités, plus ou moins adaptées suivant les cas. Je vais essayer d’être exhaustif, mais il y en a certainement d’autres !

1/ Liste de configuration

La première solution est de stocker les paramètres de configuration dans une liste de configuration, hébergée sur un site web SharePoint et même sur la console d’Administration centrale de SharePoint.

Pour cela, l’idée et de créer une définition de liste avec Visual Studio qui comprend principalement 2 colonnes :

  • Une colonne Key (clé) : permettant d’identifier uniquement le paramètre, afin de le retrouver plus facilement via une requête CAML par exemple. Sa configuration pourrait être : type Texte, obligatoire
  • Une colonne Value (valeur) : permettant de stocker la valeur au format texte. Sa configuration pourrait être : type Texte (ou texte multiligne), obligatoire
  • Des colonnes supplémentaires comme une description du paramètre, une langue, etc. peuvent être également de la partie.

L’avantage de créer une définition de liste mais également directement une instance (déployées et créées par une Feature, à la racine de la collection de site généralement) et que l’on connait l’identifiant unique du modèle (souvent 10000, 10001, …) que nous fixons nous-même ainsi que l’URL de l’instance créée. Il nous sera donc plus facile de retrouver cette instance par code.

Nous pourrons aussi déployer des données via la création de l’instance via les Rows proposées dans la déclaration de l’instance.

Un autre avantage est de proposer une interface graphique, via le navigateur pour éditer les données… l’’’interface standard de SharePoint !

Et bien sûr, la sécurité et la gestion des droits seront de la partie pour gérer plus finement ces ensembles de clés/valeurs stockées dans la liste.

On peut également penser à développer une classe de service permettant d’accéder à cette instance de liste, récupérer une valeur, ajouter, supprimer, mettre à jour.

Un inconvénient reste l’accès à cette instance de liste depuis un autre site où il faudra recourir à de l’impersonation, des accès Cross-Site et surtout entre WebApplication etc.

Mais également qu’on ne pourra stocker que des types simples ou bien il faudra sérialiser / désérialiser des objets pour les stocker.

Donc pour résumer :

  • Une solution Visual Studio
  • Une définition de liste
  • Une instance de liste
  • Une colonne clé unique
  • Une colonne valeur
  • Des colonnes supplémentaires
  • Des données poussées lors du déploiement
  • Une classe de service pour les accès par code

Voici un extrait d’une classe de service permettant de récupérer l’instance de la liste en question, il vous restera à développer le Get / Update / Add / Delete :

public class ListHelper
{
public static SPList GetParamsList(SPWeb web)
{
SPList resultList = null;
if (web != null)
{
try
{
SPSecurity.RunWithElevatedPrivileges(() =>
{
using (SPSite currentSite = new SPSite(web.Site.ID))
{
using (SPWeb currentWeb = currentSite.OpenWeb(currentSite.RootWeb.ID))
{
SPList list = currentWeb.GetList(ListConstants.ListUrl);

if (list != null)
resultList = list;
}
}
});
return resultList;
}
catch (Exception ex)
{
throw new SPException(“An error has occured. Please contact your administrator : ” + ex.Message);
}
}
else
return null;
}
}

NB : ListConstants est une classe qui contient des paramètres de configuration de ma solution Visual Studio.

2/ Property Bags

Cette seconde solution est également souvent envisagée par les développeurs. Elle permet de stocker des paramètres à plusieurs niveaux :

  • Farm (SPFarm)
  • Web Application (SPWebApplication)
  • Site Collection (SPSite)
  • Site web (SPWeb)
  • Liste (SPList)

Pour faire simple, le property bag est une Hashtable (clé/valeur), sans paramètre supplémentaire, où l’on pourra stocker des types simples sous forme de texte (ou bien en sérialisant / désérialisant les objets).

Les données sont stockées soit dans la base de données de configuration soit dans la base de données de contenu (suivant objet).

Par contre, SharePoint ne propose aucun accès graphique à ces données (pour l’édition par exemple). Toutefois on peut penser au projet SharePoint Property Bag Settings 2010 disponible sur Codeplex : http://pbs2010.codeplex.com/.

Ici également, il faut penser à l’accessibilité des données à partir d’un autre site, d’une autre WebApplication et donc utiliser de l’impersonation, une classe de service pour accéder aux données.

Voici comment mettre à jour une propriété dans le property bag d’un objet SPWeb :

if(web.Properties[“Key”] == null)
{
web.Properties.Add(“Key”, “Value”);
web.Properties.Update();
}

string storedValue = web.Properties[“Key”];
web.Properties[“Key”] = “NewValue”;
web.Properties.Update();

3/ Session / cookie

La troisième solution est de recourir au stockage de données dans la session de l’utilisateur ou dans un cookie ou dans le Viewstate.

Ici, les objets ne sont donc pas stockés dans SharePoint mais bien dans des objets spécifiques à chaque utilisateur et ne pourront pas être partagés entre-eux. Il faudra donc charger les données, les mettre à jour pour chaque utilisateur.

Cela ne correspond donc pas exactement aux cas fonctionnels précédents, mais il est bon de le citer car c’est parfois bien pratique de stocker des données temporaires et qui peuvent permettre d’accélerer le chargement des pages.

Pour le cas de la session, il vous faudra penser à activer la session ASP.Net sur les serveurs IIS hébergeant SharePoint (http://technet.microsoft.com/fr-fr/library/ff607857(v=office.15).aspx).

La session permet de stocker des type simples sous forme de string et nous devrons sérialiser/désérialiser les objets.

Pour stocker une valeur dans la session de l’utilisateur, on peut utiliser le script suivant :

if(HttpContext.Current.Session[“MyKEY”] == null)
{
HttpContext.Current.Session.add (“MyKEY”, “MyVALUE”);
}

4/ Fichiers de configuration

Quatrième option, utiliser le fichier de configuration de la WebApplication : web.config pour stocker des paramètres, ici aussi de type texte. Pour cela, Microsoft fournit une API permettant d”insérer des clés, de le lire, supprimer. En général, on stocke ces paramètres dans la section AppSettings du fichier, ou en créant une section spécifique (qu’il faudra également penser à créer).

Le simple fait de déployer des paramètres à cet emplacement redémarrera le pool IIS afin qu’ils soient pris en compte. Ce redémarrage se fera automatiquement grâce à un Handler positionné par IIS sur le fichier web.config et donc aucune action du développeur ne sera demandée. Attention que cela ne pose pas de problème aux utilisateurs (indisponibilité de quelques secondes / minutes, le temps du redémarrage).

Quelques bugs ont été constatés lors de l’utilisation de cette méthode. Je vous invite à faire une petite recherche à ce sujet.

Généralement, le développeur déploie ces modifications lors de l’activation d’une Feature :

public override void FeatureActivated(SPFeatureReceiverProperties properties) {

SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;

SPWebConfigModification myModification = new SPWebConfigModification();

myModification.Path = “configuration/appSettings”;    myModification.Name = “add [@key=’mySetting’] [@value=’myValue’]”;

myModification.Sequence = 0;

myModification.Owner = “DOMAIN\OWNERLOGIN”;

myModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;

myModification.Value = “”;    webApp.WebConfigModifications.Add(myModification);

webApp.Update();

webApp.Farm.Services.GetValue().ApplyWebConfigModifications();

}

Il faut bien sur penser à nettoyer lors de la désactivation de la Feature !

 

5/ Objets persistés : SPPersistedObject

Cette cinquième méthode, de mémoire, est arrivée avec SharePoint 2010. Elle permet de stocker des objets complexes, de manière hiérarchique, dans une source de données globale à la plateforme, et peut donc être partagée entre les utilisateurs. Ces objets seront stockés dans la base de données de configuration de la plateforme SharePoint (base de donnée SharePoint_Config).

C’est donc une méthode évoluée en regard des précédentes ! Quelques contraintes sont toutefois à remarquer. En effet, les objets stockés doivent hériter de la classe SPPersistedObject, une annotation (GUID) doit être précisée sur la classe (identifiant unique de l’objet), un constructeur par défaut et un constructeur avec deux paramètres (string => nom de l’objet, SPPersistedObject => l’objet en lui-même). et enfin vos propriétés personalisées. Rien d’insurmontable donc !

Quelques avertissement cependant : le hierarchical store n’est accessible qu’au Farm Account de la ferme SharePoint, et donc pas à tous les utilisateurs. Pensez donc à utiliser l’impersonation pour accéder aux données !

NB : les timerjobs SharePoint sont exécutés avec ce Farm Account, c’est donc un moyen pratique de stocker les données de configuration pour ces TimerJobs !

[Guid(“4DB9AF54-1339-424A-BE2D-648940610283”)]
public class MyPersistedClass : SPPersistedObject
{
public MyPersistedClass()
{
}
public MyPersistedClass(string name, SPPersistedObject parent) : base(name, parent)
{
}
[Persisted]
string Value1;
[Persisted]
string Value2;
[Persisted]
int Value3;
}

Et pour accéder aux données :

SPFarm farm = SPFarm.Local;
PersistedClass rootClass = new PersistedClass(“MyFirstItem”, farm);
rootClass.Value1 = “BLA BLA BLA”;
rootClass.Value2 = “PLOP PLOP PLOP”;
rootClass.Value3 = 8;
rootClass.Update(); PersistedClass childClass = new PersistedClass(“MyFirstItemChild”, rootClass);
childClass.Value1 = “YOUPI”;
childClass.Update(); SPFarm farm = SPFarm.Local;
PersistedClass retrievedValue = farm.GetChild(“MyFirstItem”);

 

6/ Cache Distribué (SP2013)

Dans cette sixième méthode, nous allons aborder une nouveauté de SharePoint 2013 : le Cache Distribué (Distributed Cache) qui peut être une bonne alternative pour le stockage d’objets complexes.

En effet ce dernier propose de maintenir en cache des données / objets sur une durée fixée et paramétrable lors de l’ajout des données dans ce cache et de partager ces données entre les différents serveurs de la ferme SharePoint, entre les utilisateurs.

Pour utiliser ce cache, je suis tombé sur une classe toute prête (et testée dans un projet) qui vous permet d’ajouter, lire, supprimer et modifier les données stockées. Vous la trouverez ici : https://github.com/Almond-Labs/SP2013-Starter/blob/master/Source/AL.Sharepoint.Core/Cache/CacheManager.cs

Il vous suffira de recréer cette classe dans votre projet Visual Studio, de référencer les assemblies nécessaires (recherchez les dans le répertoire 15) et de compiler. Ca fait gagner du temps…

Avantage également de cette source, l’auteur fournit des méthodes génériques pour stocker des objets… et donc nous pourrons stocker des objets complexes dans le cache, sans les sérialiser.

A noter dans la méthode Put qu’un TimerSpan est passé en paramètre. Il permet de fixer la durée de conservation des données dans le cache distribué :

public static void Put<T>(string key, T value, TimeSpan timeSpan)

Par exemple, nous appelerons la méthode Put qui permettra de stocker l’objet MyObjectInstance de type MyObject pendant 1h30. :

CacheManager.Put<MyObject> (“MyKEY”, MyObjectInstance, 1,30,0);

Cette méthode a donc l’avantage de stocker directement des objets durant une période fixée, partageable entre les utilisateurs.

 

7/ Application de Service

Cette dernière méthode est un peu bourrine plus complexe. Elle demande le développement d’une application de service (Service Application) pour SharePoint, proposant un magasin de données centralisé à toute la ferme SharePoint. (et même entre fermes avec du multi-tenant).

Pour cela, je vous conseille de vous tourner vers Technet : http://msdn.microsoft.com/en-us/library/gg193964(v=office.14).aspx ou encore http://msdn.microsoft.com/fr-fr/library/gg543112(v=office.14).aspx.

Ce n’est pas chose aisée, mais dans certains cas cela peut répondre à votre besoin. Par exemple nous pourrions imaginer que nous souhaitons stocker un catalogue important de données de configuration, spécifiques à chaque utilisateur.

Nous utiliserons pour cela une base de données spécifique déployée par l’application de  services, des WebServices afin d’accéder aux données depuis chacun de sites, WebParts, composants personnalisés ou même des applications SharePoint (Apps). Sans oublier la possibilité de requêter ce service depuis une application métier, sur des terminaux mobiles, etc.

[SharePoint 2010 – 2013] – Créer une Target Application sans le Secure Store Service en PowerShell

Posted on Updated on

 

Bonjour à tous,

Cela faisait un petit moment que je n’avais pas publié. Un petit post aujourd’hui pour vous montrer comment ajouter une TargetApplication dans le Secure Store Service de SharePoint. Allons-y !

 

1/ Secure… quoi ?

Le Secure Store Service, appelé Banque d’Informations Sécurisées en français), est une application de service de SharePoint 2010 et 2013 qui vous permet de stocker des couples d’identifiants login/password dans une base encryptée. Ces couples d’identifiants sont destinés à l’usage d’autres applications de services : Business Connectivity Service, PowerPivot, Excel Services, etc. afin qu’ils soient en capacité à se connecter à des sources de données par exemple, avec des identifiants différents de ceux de l’utilisateur connecté, du pool d’application, du compte administrateur.

Dans mon cas, il s’agit de stocker des identifiants afin qu’une application personnalisée puisse se connecter à un serveur Exchange 2010 via ses WebServices. Je ne voulais pas stocker ces informations dans SharePoint ou dans un fichier de configuration par exemple. L’avantage étant que ces paramètres sont cryptés et modifiables par l’administrateur de la ferme.

 

2/ Prérequis

En prérequis, il faut bien sûr déployer cette application de service qui sera disponible pour :

  • · SharePoint Server 2010 Standard
  • · SharePoint Server 2010 Enterprise
  • · SharePoint Server 2013 Standard
  • · SharePoint Server 2013 Enterprise

Point sur n’importe laquelle des versions Foundation ni SharePoint 2007 donc.

Pour déployer et configurer cette application de service, je vous invite à lire : http://technet.microsoft.com/fr-fr/library/ee806866(v=office.15).aspx

 

3/ Un peu de PowerShell

Cette démo sera réalisée avec SharePoint Server 2010 Enterprise.

Pour commencer, nous allons lancer le Management Shell de SharePoint (PowerShell avec les assemblies/cmdlets nécessaires à l’utilisation avec SharePoint). Pour cela, vous trouverez le raccourci dans Démarrer > Tous les Programmes > Microsoft SharePoint 2010 Products > SharePoint 2010 Management Shell

image

 

Nous allons commencer par renseigner quelques variables nécessaires :

  • $siteurl = ” http://sp2010-dev:82/sites/florent&#8221; ==> Url d’un site pour récupérer le ServiceContext (L’application de service Secure Store Service doit être associée à cette WebApplication !)
  • $ta_name = “ExchangeWS” ==> Nom de ma Target Application
  • $ta_friendlyName = “ExchangeWS for DEMO” ==> Nom “Friendly” de ma Target Application
  • $ta_contactEmail = “admin@sp2010.local” ==> Adresse e-mail de contact
  • $ta_owner = “DEMO\spadmin” ==> Propriétaire de la Target Application
  • $ta_userName = “DEMO\exchangeuser” ==> Login à stocker
  • $ta_password = “P@ssw0rd” ==> Password à stocker

image

Puis on créé la Target Application :

$target = New-SPSecureStoreTargetApplication -Name $ta_name -FriendlyName $ta_friendlyName -ContactEmail $ta_contactEmail -ApplicationType Group

clip_image002

Puis on créé les champs Login et password à stocker :

$usernameField = New-SPSecureStoreApplicationField -name “Exchange Username” -Type WindowsUserName -Masked:$false

$passwordField = New-SPSecureStoreApplicationField -name “Exchange Password” -Type WindowsPassword -Masked:$true

$fields = $usernameField,$passwordField

clip_image004

Puis nous allons créer 2 claims pour l’administrateur et pour le propriétaire :

$adminClaims = New-SPClaimsPrincipal -Identity $a_owner -IdentityType 1

$ownerClaims = New-SPClaimsPrincipal -Identity $a_owner -IdentityType 1

clip_image006

Puis créer la nouvelle Target Application :

New-SPSecureStoreApplication -ServiceContext $contextUrl -TargetApplication $ta -Fields $fields -Administrator $adminClaims -CredentialsOwnerGroup $ownerClaims

$ssa = Get-SPSecureStoreApplication -ServiceContext $contextUrl -Name $ta.Name

clip_image008

Puis on charge les identifiants :

$user = ConvertTo-SecureString $ta_userName -AsPlainText -Force

$password = ConvertTo-SecureString $ta_password -AsPlainText -Force

$credentials = $user,$password

Update-SPSecureStoreGroupCredentialMapping -Identity $ssa -Values $credentials

clip_image010

On peut verifier dans l’administration centrale, la Target Application est bien créée :

clip_image012

clip_image014

clip_image016

On voit ici que les Members (utilisateurs ayant accès à la Target Application) contiennent seulement SPADMIN. Pour ajouter des utilisateurs, on peut modifier les Owner Claims…

clip_image018

Par contre, impossible de valider graphiquement si le login/password est bien ajouté, la fenêtre ne charge pas les valeurs chargées (formulaire vide par défaut). Il faut donc tester… et chez moi ça marche 😉

A bientôt !

Florent.

[eBooks] – Collection d’ebooks gratuits

Posted on Updated on

Bonjour à tous.

 

Aujourd’hui, pas d’article technique mais une collection d’ebooks gratuits à télécharger (en anglais) de tous types :

  • Office & Office 365
  • SharePoint
  • SQL Server
  • System Center
  • Visual Studio
  • Web development
  • Windows
  • Windows Azure

Et en plusieurs formats pour la plupart : PDF, EPUB, MOBI. On ne va pas se priver !

Ca se passe par ici : http://blogs.msdn.com/b/mssmallbiz/archive/2013/06/18/huge-collection-of-free-microsoft-ebooks-for-you-including-office-office-365-sharepoint-sql-server-system-center-visual-studio-web-development-windows-windows-azure-and-windows-server.aspx

 

Bonne lecture !