Sei sulla pagina 1di 7

12/6/2015

Chapter18.Customauthentication

Chapter18.Customauthentication
Guacamole'sauthenticationlayerisdesignedtobeextendablesuchthatuserscanintegrateGuacamoleinto
existing authentication systems without having to resort to writing their own web application around the
GuacamoleAPI.
The web application comes with a default authentication mechanism which uses an XML file to associate
users with connections. Plugins for Guacamole that provide LDAPbased authentication or databasebased
authenticationhavealsobeendeveloped.
To demonstrate the principles involved, we will implement a very simple authentication plugin which
associatesasingleuser/passwordpairwithasingleconnection,withallthisinformationsavedinproperties
insidetheguacamole.propertiesfile.
In general, all other authentication plugins for Guacamole will use the principles demonstrated here.
However, as of Guacamole 0.8.0, the authentication model has been significantly enhanced, and supports
morethansimplytranslatingausername/passwordpairintoasetofauthorizedconfigurations.Thistutorial
demonstratesthesimplestwaytocreate an authentication plugin for Guacamole an authentication plugin
thatdoesnotsupportmanagementofusersandconnectionsviathewebinterface.

Guacamole'sauthenticationmodel
When you view any page in Guacamole, whether that be the login screen or the client interface, the page
makes an authentication attempt with the web application, sending all available credentials. After entering
your username and password, the exact same process occurs, except the web application receives the
usernameandpasswordaswell.
The web application handles this authentication attempt by collecting all credentials available and passing
themtoadesignatedclasscalledthe"authenticationprovider".Thisclassisdesignatedviaapropertyinthe
guacamole.properties file. Given the set of credentials, the specified authentication provider returns a
contextobjectthatprovidesrestrictedaccesstootherusersandconnections,ifany.

AGuacamolepluginskeleton
For simplicity's sake, and because this is how things are done upstream in the Guacamole project, we will
useMaventobuildourplugin.
ThebareminimumrequiredforaGuacamoleauthenticationpluginisapom.xmlfilelistingguacamoleextas
adependency,andasingle.javafileimplementingourstubofanauthenticationprovider.
Inourstub,wewon'tactuallydoanyauthenticationyetwe'lljustuniversallyrejectallauthenticationattempts
byreturningnullforanycredentialsgiven.Youcanverifythatthisiswhathappensbycheckingtheserver
logs.
Example18.1.Barebonespom.xmlrequiredforasimpleauthenticationplugin.
<projectxmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/mavenv4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.glyptodon.guacamole</groupId>
<artifactId>guacamoleauthtutorial</artifactId>
<packaging>jar</packaging>
<version>0.9.7</version>
http://guacdev.org/doc/gug/customauthentication.html

1/7

12/6/2015

Chapter18.Customauthentication

<name>guacamoleauthtutorial</name>
<url>http://guacdev.org/</url>
<properties>
<project.build.sourceEncoding>UTF8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<!Writtenfor1.6>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>mavencompilerplugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!GuacamoleJavaAPI>
<dependency>
<groupId>org.glyptodon.guacamole</groupId>
<artifactId>guacamolecommon</artifactId>
<version>0.9.7</version>
</dependency>
<!GuacamoleExtensionAPI>
<dependency>
<groupId>org.glyptodon.guacamole</groupId>
<artifactId>guacamoleext</artifactId>
<version>0.9.7</version>
</dependency>
</dependencies>
</project>

Wewon'tneedtoupdatethispom.xmlthroughouttherestofthetutorial.Evenafteraddingnewfiles,Maven
willjustfindthemandcompileasnecessary.
Naturally,weneedtheactualauthenticationpluginskeletoncode.Whileyoucanputthisinwhateverfileand
package you want, for the sake of this tutorial, we will assume you are using
org.glyptodon.guacamole.auth.TutorialAuthenticationProvider.
Example18.2.AskeletonTutorialAuthenticationProvider
packageorg.glyptodon.guacamole.auth;
importjava.util.Map;
importorg.glyptodon.guacamole.GuacamoleException;
importorg.glyptodon.guacamole.net.auth.simple.SimpleAuthenticationProvider;
importorg.glyptodon.guacamole.net.auth.Credentials;
http://guacdev.org/doc/gug/customauthentication.html

2/7

12/6/2015

Chapter18.Customauthentication

importorg.glyptodon.guacamole.protocol.GuacamoleConfiguration;
publicclassTutorialAuthenticationProviderextendsSimpleAuthenticationProvider{

@Override
publicMap<String,GuacamoleConfiguration>
getAuthorizedConfigurations(Credentialscredentials)
throwsGuacamoleException{
//Donothing...yet
returnnull;
}
}

To
conform
with
Maven,
this
skeleton
file
must
be
placed
within
src/main/java/net/sourceforge/guacamole/authasTutorialAuthenticationProvider.java.
Noticehowsimpletheauthenticationprovideris.TheAuthenticationProvider interface requires nothing
more than a single getAuthorizedConfigurations() implementation, which must return a Map of
GuacamoleConfigurationeachassociatedwithsomearbitraryuniqueID.ThisuniqueIDwillbepresented
totheuserintheconnectionlistaftertheylogin.
Fornow,wejustreturnnull,whichwillcauseGuacamoletoreportaninvalidloginforeveryattempt.Note
that there is a difference in semantics between returning an empty map and returning null, as the former
indicates the credentials are authorized but simply have no associated configurations, while the latter
indicatesthecredentialsarenotauthorizedatall.

Actuallyauthenticatingtheuser
Once we receive credentials, we need to validate those credentials against the associated properties in
guacamole.properties(oursourceofauthenticationinformationforthesakeofthistutorial).
Wewilldefinefourproperties:
tutorialuser
Thenameoftheonlyuserweaccept.
tutorialpassword
Thepasswordwerequirefortheuserspecifiedtobeauthenticated.
tutorialprotocol
Theprotocoloftheconfigurationthisuserisauthorizedtouse,whichwillbesenttoguacdwhenthe
userlogsinandselectstheirconnection.
tutorialparameters
A commadelimited list of name = value pairs. For the sake of simplicity, we'll assume there will
neverbeanycommasinthevalues.
Iftheusernameandpasswordmatchwhatisstoredinthefile,wereadtheconfigurationinformation,storeit
inaGuacamoleConfiguration,andreturntheconfigurationwithinaset,tellingGuacamolethatthisuseris
authorizedbutonlytoaccesstheconfigurationsreturned.
Upstream,wealwaysplacethepropertiesofauthenticationprovidersintheirownclass,andsowewillalso
dothathereinthistutorial,asitkeepsthingsorganized.
http://guacdev.org/doc/gug/customauthentication.html

3/7

12/6/2015

Chapter18.Customauthentication

Example18.3.TutorialProperties.java,aclasscontainingpropertydefinitions
packageorg.glyptodon.guacamole.auth;
importorg.glyptodon.guacamole.properties.StringGuacamoleProperty;
publicclassTutorialGuacamoleProperties{
/**
*Thisclassshouldnotbeinstantiated.
*/
privateTutorialGuacamoleProperties(){}
/**
*Theonlyusertoallow.
*/
publicstaticfinalStringGuacamolePropertyTUTORIAL_USER=
newStringGuacamoleProperty(){
@Override
publicStringgetName(){return"tutorialuser";}
};
/**
*Thepasswordrequiredforthespecifieduser.
*/
publicstaticfinalStringGuacamolePropertyTUTORIAL_PASSWORD=
newStringGuacamoleProperty(){
@Override
publicStringgetName(){return"tutorialpassword";}
};
/**
*Theprotocoltousewhenconnecting.
*/
publicstaticfinalStringGuacamolePropertyTUTORIAL_PROTOCOL=
newStringGuacamoleProperty(){
@Override
publicStringgetName(){return"tutorialprotocol";}
};
/**
*Allparametersassociatedwiththeconnection,asacommadelimited
*listofname="value"
*/
publicstaticfinalStringGuacamolePropertyTUTORIAL_PARAMETERS=
newStringGuacamoleProperty(){
@Override
publicStringgetName(){return"tutorialparameters";}
};
http://guacdev.org/doc/gug/customauthentication.html

4/7

12/6/2015

Chapter18.Customauthentication

Normally, we would define a new type of GuacamoleProperty to handle the parsing of the parameters
requiredbyTUTORIAL_PARAMETERS,butforthesakeofsimplicity,parsingofthisparameterwillbeembedded
intheauthenticationfunctionlater.
You will need to modify your existing guacamole.properties file, adding each of the above properties to
describeoneofyouravailableconnections.
Example18.4.Propertiesdescribingauserandconnection,asrequiredbythistutorial
#Usernameandpassword
tutorialuser: tutorial
tutorialpassword: password
#Connectioninformation
tutorialprotocol: vnc
tutorialparameters: hostname=localhost,port=5900

Oncethesepropertiesandtheiraccessorclassareinplace,it'ssimpleenoughtoreadthepropertieswithin
getAuthorizedConfigurations()andauthenticatetheuserbasedontheirusernameandpassword.
Example18.5.Checkingthecredentialsagainsttheproperties
@Override
publicMap<String,GuacamoleConfiguration>
getAuthorizedConfigurations(Credentialscredentials)
throwsGuacamoleException{
//Getusername
Stringusername=GuacamoleProperties.getRequiredProperty(
TutorialProperties.TUTORIAL_USER
);
//Ifwrongusername,fail
if(!username.equals(credentials.getUsername()))
returnnull;
//Getpassword
Stringpassword=GuacamoleProperties.getRequiredProperty(
TutorialProperties.TUTORIAL_PASSWORD
);
//Ifwrongpassword,fail
if(!password.equals(credentials.getPassword()))
returnnull;
//Successfullogin.Returnconfigurations(STUB)
returnnewHashMap<String,GuacamoleConfiguration>();
}

http://guacdev.org/doc/gug/customauthentication.html

5/7

12/6/2015

Chapter18.Customauthentication

Asis,theauthenticationproviderwillworkinitscurrentstateinthatthecorrectusernameandpasswordwill
authenticatetheuser,whileanincorrectusernameorpasswordwillnot,butwestillaren'treturninganactual
map of configurations. We need to construct the configuration based on the properties in the
guacamole.propertiesfileaftertheuserhasbeenauthenticated,andreturnthatconfigurationtotheweb
application.

Parsingtheconfiguration
The only remaining task before we have a fullyfunctioning authentication provider is to parse the
configurationfromtheguacamole.propertiesfile.
Example18.6.ParsingandreturningaGuacamoleConfiguration
@Override
publicMap<String,GuacamoleConfiguration>
getAuthorizedConfigurations(Credentialscredentials)
throwsGuacamoleException{
//Getusername
Stringusername=GuacamoleProperties.getRequiredProperty(
TutorialProperties.TUTORIAL_USER
);
//Ifwrongusername,fail
if(!username.equals(credentials.getUsername()))
returnnull;
//Getpassword
Stringpassword=GuacamoleProperties.getRequiredProperty(
TutorialProperties.TUTORIAL_PASSWORD
);
//Ifwrongpassword,fail
if(!password.equals(credentials.getPassword()))
returnnull;
//Successfullogin.Returnconfigurations.
Map<String,GuacamoleConfiguration>configs=
newHashMap<String,GuacamoleConfiguration>();
//Createnewconfiguration
GuacamoleConfigurationconfig=newGuacamoleConfiguration();
//Setprotocolspecifiedinproperties
config.setProtocol(GuacamoleProperties.getRequiredProperty(
TutorialProperties.TUTORIAL_PROTOCOL
));
//Setallparameters,splittingatcommas
for(StringparameterValue:GuacamoleProperties.getRequiredProperty(
TutorialProperties.TUTORIAL_PARAMETERS
).split(",\\s*")){
//Findtheequalssign
intequals=parameterValue.indexOf('=');
if(equals==1)
thrownewGuacamoleException("Requiredequalssignmissing");
//Getnameandvaluefromparameterstring
Stringname=parameterValue.substring(0,equals);
http://guacdev.org/doc/gug/customauthentication.html

6/7

12/6/2015

Chapter18.Customauthentication

Stringvalue=parameterValue.substring(equals+1);
//Setparameterasspecified
config.setParameter(name,value);
}
configs.put("DEFAULT",config);
returnconfigs;
}

http://guacdev.org/doc/gug/customauthentication.html

7/7

Potrebbero piacerti anche