Canigó - Servei Seguretat
SERVEI SEGURETAT
IntroduccióPropòsitEl Servei de Seguretat té com a propòsit principal gestionar l'autentificació i l'autorització dels usuaris de les nostres aplicacions. L'objectiu de l'autentificació és comprovar que l'usuari és qui diu ser, mentre que l'autorització s'encarrega de comprovar que realment té accés al recurs sol- licitat. NOTA: L'especificació JAAS (Java Authorization and Authentication) de J2EE proporciona els mecanismes necessaris de seguretat. Cada servidor d'aplicacions pot implementar l'estàndard però ho fa de diferents formes produint problemes de compatibilitat. Actualment, i a causa del seu grau de maduresa i facilitat canigo recomana l'ús de 'Acegi' com framework base i les extensions que canigo proporciona. Per a l'ús d'aquest servei i la lectura del present document es necessiten com a prerequisits els següens aspectes:
Context i Escenari d'úsEl Servei de Seguretat és un servei general de canigo.
Versions i DependènciesLes dependències descrites a la següent url son requerides per tal de compilar i fer funcionar el projecte: A qui es dirigeixAquest document es dirigeix als perfils següents:
Documents i Fonts de Referència
GlossariACLs (Access Control List) Les llistes de control d'accés o ACLs permeten gestionar les autoritzacions de cada rol o usuari a nivell de dades o instàncies de lògica de negoci. Per a cada instància es poden especificar diferents dret: lectura, escriptura, esborrat, creació. Descripció DetalladaArquitectura BàsicaEn el present apartat es mostren els diagrames de seqüència associats al tractament de peticions i cóm el servei de seguretat activarà el pas o no al recurs sol- licitat. Accés a una url no protegidaSi hi ha un accés a una url que no s'ha configurat com a protegida (veure apartat 'Configuració') es segueixen els següents pasos:
Accés a urls protegides
![]() Si s'accedeix a una url protegida, el funcionament és:
Accés a urls protegides si usuari autentificatSi el mateix usuari amb un rol 1 intenta accedir a una url restringida pel rol 2, la seqüència és:
Interfícies i Components GenèricsInterfícies PrincipalsNomés la interfície 'SecurityService' serà visible des de les classes desenvolupades per les aplicacions, les restants classes s'usaran per definir mitjançant la configuració el comportament dessitjat per la seguretat. Es pot trobar tota la documentació JavaDoc y el codi font referent aquests components a les següents urls: JavaDoc: http://canigo.ctti.gencat.net/confluence/canigodocs/site/canigo2_0/canigo-services-security/apidocs/index.html Instal- lació i ConfiguracióPrerequisit: Per al funcionament correcte d'aquest servei és important haver realitzat prèviament les configuracions especificades de la part 'Configuració Bàsica' del document 'Servei de Presentació'. Per a la instal- lació del Servei de Seguretat necessitem usar el fitxer 'canigo-services-security.jar' i les dependències indicades en l'apartat 'Versions i Dependències'. La configuració del servei de seguretat es descompon en les parts següents:
El Servei de Seguretat de canigo encapsula la complexitat de "Acegi" per mitjà d'una configuració simplificada i centralitzada en dos beans: authenticationConfiguration i authorizationConfiguration. NOTA prèvia: ![]() Exemple: <bean id="authorizationConfiguration" class="net.gencat.ctti.canigo.services.security. AuthorizationSecurityConfiguration"> ... <property name="beanNamesPatternList"> <list> <value> ?businessService</value> </list> </property> </bean> Per a més informació sobre el framework "Acegi", consultar la pàgina http://acegisecurity.sourceforge.net/suggested.html Configuració de la Base de DadesPer l'ús de la seguretat canigo utilitza, per defecte, l'esquema de base de dades mostrat a continuació: ![]() NOTA: Si la base de dades d'usuaris ja existeix en el moment d'implantació de canigo, no cal crear les taules d'autentificació 'USER_LOGIN', 'PARTY_ROLE' i 'ROLE'. Haurem d'indicar les query per a obtenir el nom d'usuari, password i rol. Taules d'Autentificació # USER_LOGIN
# ROLE
# PARTY_ROLE
Taules d'Autorització Les taules d'autorització només són necessàries si necessitem gestionar les autoritzacions a nivell d'instàncies de la lògica de negoci (ACLs). # ACL_OBJECT_IDENTITY
La taula ACL_PERMISSION conté els permisos que s'apliquin als usuaris o rols per a cada objecte de la lògica de negoci. Conté els camps següents:
Per a la creació de l'esquema podem fer ús del script següent per Oracle:
DROP SEQUENCE ACL_PERMISSION_SEQ; DROP SEQUENCE ACL_OBJECT_SEQ; DROP SEQUENCE PARTY_OBJECT_SEQ; DROP SEQUENCE ROLE_OBJECT_SEQ; create sequence ROLE_OBJECT_SEQ start with 1 increment by 1; create sequence ACL_OBJECT_SEQ start with 1 increment by 1; create sequence ACL_PERMISSION_SEQ start with 1 increment by 1; create sequence PARTY_OBJECT_SEQ start with 1 increment by 1; DROP TABLE ACL_PERMISSION; DROP TABLE ACL_OBJECT_IDENTITY; DROP TABLE PARTY CASCADE CONSTRAINTS; DROP TABLE GROUP_ROLE CASCADE CONSTRAINTS; DROP TABLE PARTY_GROUP CASCADE CONSTRAINTS; DROP TABLE PARTY_RELATIONSHIP CASCADE CONSTRAINTS; DROP TABLE PARTY_ROLE CASCADE CONSTRAINTS; DROP TABLE ROLE CASCADE CONSTRAINTS; DROP TABLE USER_LOGIN CASCADE CONSTRAINTS; CREATE TABLE acl_object_identity ( id NUMBER PRIMARY KEY, object_identity VARCHAR2(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR2(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ); CREATE TABLE acl_permission ( id NUMBER PRIMARY KEY, acl_object_identity NUMBER NOT NULL, recipient VARCHAR2(100) NOT NULL, mask NUMBER NOT NULL, CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) ); CREATE TABLE PARTY ( PARTY_ID NUMBER NOT NULL, PARTY_TYPE_ID NUMBER, EXTERNAL_ID VARCHAR2(20), CREATED_DATE VARCHAR2(255), CREATED_BY_USER_LOGIN VARCHAR2(255), LAST_MODIFIED_DATE VARCHAR2(255), LAST_MODIFIED_BY_USER_LOGIN VARCHAR2(255), LAST_UPDATED_STAMP VARCHAR2(255), LAST_UPDATED_TX_STAMP VARCHAR2(255), CREATED_STAMP VARCHAR2(255), CREATED_TX_STAMP VARCHAR2(255), CONSTRAINT PK_PARTY_ID UNIQUE(PARTY_ID) ) ; CREATE TABLE PARTY_GROUP ( PARTY_ID NUMBER NOT NULL, GROUP_PARENT_ID NUMBER NULL, GROUP_NAME VARCHAR2(255) NOT NULL, CONSTRAINT PK_PARTY_GROUP UNIQUE(PARTY_ID) ) ; CREATE TABLE PARTY_RELATIONSHIP ( PARTY_ID_FROM NUMBER NOT NULL, PARTY_ID_TO NUMBER NOT NULL, TYPE NUMBER NULL, CONSTRAINT PK_PARTY_RELATIONSHIP UNIQUE(PARTY_ID_FROM, PARTY_ID_TO), FOREIGN KEY (PARTY_ID_FROM) REFERENCES PARTY(PARTY_ID), FOREIGN KEY (PARTY_ID_TO) REFERENCES PARTY(PARTY_ID) ) ; CREATE TABLE ROLE ( ROLE_ID NUMBER NOT NULL, ROLE_ID_PARENT NUMBER, ROLE_NAME VARCHAR2(50) NOT NULL, ROLE_DESCRIPTION VARCHAR2(255), CONSTRAINT PK_ROLE UNIQUE(ROLE_ID), FOREIGN KEY (ROLE_ID_PARENT) REFERENCES ROLE(ROLE_ID) ) ; CREATE TABLE USER_LOGIN ( USER_LOGIN_ID VARCHAR2(50) NOT NULL, PARTY_ID NUMBER NOT NULL, PASSWORD VARCHAR2(50) NOT NULL, CONSTRAINT PK_USER_LOGIN UNIQUE(USER_LOGIN_ID), FOREIGN KEY (PARTY_ID) REFERENCES PARTY_GROUP(PARTY_ID) ) ; CREATE TABLE PARTY_ROLE ( USER_LOGIN_ID VARCHAR2(50) NOT NULL, ROLE_ID NUMBER NOT NULL, CONSTRAINT PK_PARTY_ROLE UNIQUE(USER_LOGIN_ID, ROLE_ID), FOREIGN KEY (USER_LOGIN_ID) REFERENCES USER_LOGIN(USER_LOGIN_ID), FOREIGN KEY (ROLE_ID) REFERENCES ROLE(ROLE_ID) ) ; CREATE TABLE GROUP_ROLE ( PARTY_ID NUMBER NOT NULL, ROLE_ID NUMBER NOT NULL, CONSTRAINT PK_GROUP_ROLE UNIQUE(PARTY_ID, ROLE_ID), FOREIGN KEY (PARTY_ID) REFERENCES PARTY_GROUP(PARTY_ID), FOREIGN KEY (ROLE_ID) REFERENCES ROLE(ROLE_ID) ) ; CREATE OR REPLACE TRIGGER ACL_OBJ_TRIGGER before insert on ACL_OBJECT_IDENTITY for each row begin select ACL_OBJECT_SEQ.nextval into :new.id from dual; end; CREATE OR REPLACE TRIGGER ACL_PERMISSION_TRIGGER before insert on ACL_PERMISSION for each row begin select ACL_PERMISSION_SEQ.nextval into :new.id from dual; end; CREATE OR REPLACE TRIGGER PARTY_OBJECT_SEQ_TRIGGER before insert on PARTY_GROUP for each row WHEN (new.PARTY_ID is null) begin select PARTY_OBJECT_SEQ.nextval into :new.PARTY_ID from dual; end; CREATE OR REPLACE TRIGGER CANIGO.ROLE_OBJECT_SEQ_TRIGGER before insert on ROLE for each row WHEN (new.ROLE_ID is null) begin select ROLE_OBJECT_SEQ.nextval into :new.ROLE_ID from dual; end; Configuració dels filtres de l'Aplicació WebFitxer de configuració: web.xml Acegi usa un conjunt de filtres per a detectar aspectes de l'autorització i autentificació. Per a usar-los definirem en el fitxer 'WEB-INF/web.xml el codi següent:
<!-- Filter ACEGI, using a FilterChainProxy makes it easier to configure different Filters in the Spring application context configuration file--> <filter> <filter-name>Acegi Filter Chain Proxy</filter-name> <filter-class> net.sf.acegisecurity.util.FilterToBeanProxy </filter-class> <init-param> <param-name>targetClass</param-name> <param-value> net.sf.acegisecurity.util.FilterChainProxy </param-value> </init-param> </filter> <filter-mapping> <filter-name>Acegi Filter Chain Proxy</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> Per a més informació consultar la pàgina http://acegisecurity.sourceforge.net/docbook/acegi.html#security-filters Configuració de la font de dades de SeguretatFitxer de configuració: canigo-services-security.xml El Servei de Seguretat necessita conèixer com connectar-se a l'esquema de base de dades que defineix les taules anteriorment comentades. Per a això, hem d'especificar un bean 'dataSource' en el que configurarem les propietats de la base de dades. Es recomana l'ús de JNDI per a definir la font de dades. Exemple amb jndi:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/JNDISource..."/> </bean> Exemple amb jdbc:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>$\{jdbc.driverClassName\}</value> </property> <property name="url"> <value>$\{jdbc.url\}</value> </property> <property name="username"> <value>$\{jdbc.username\}</value> </property> <property name="password"> <value>$\{jdbc.password\}</value> </property> <bean> Configuració de l'AutentificacióEn la configuració de l'Autentificació tindrem en consideració:
Configuració de la Font d'Autorització per Base de Dades Fitxer de configuració: canigo-services-security.xml La configuració de l'autentificació per mitjà de base de dades es realitza per mitjà del bean de la classe 'net.gencat.ctti.canigo.services.
Exemple:
<bean id="databaseAuthenticationConfiguration1" class="net.gencat.ctti.canigo.services.security. DatabaseAuthenticationConfiguration"> <!- Propietats obligatóries -> <property name ="passwordEncoderClass" value ="net.sf.acegisecurity.providers.encoding. PlaintextPasswordEncoder" /> <!- Propietats opcionals -> <property name ="usersByUserNameQuery"> <value> SELECT \{Nombre_usuario\}, \{contraseña\} * FROM* \{usuarios\} _ WHERE \{_Nombre_usuario\} =? </value> </property> <property name ="authoritiesbyUserNameQuery"> <value> SELECT \{Nombre_usuario\}, \{rol\} * FROM* \{privilegios\} _ WHERE \{_Nombre_usuario\} =? </value> </property> </bean> Configuració de la Font d'Autorització per LDAP Fitxer de configuració: canigo-services-security.xml En el cas que es requereixi configurar l'autentificació per mitjà de crides directes a LDAP podem fer ús d'una classe diferent. Per a realitzar les proves en desenvolupament podem instal- lar un servidor LDAP senzill (veure l'apartat 'Eines de Suport' per a més referència). La configuració de l'accés al LDAP es fa per mitjà d'un bean de la classe 'net.gencat.ctti.canigo.services.
Exemple:
<bean id="ldapAuthenticationConfiguration" class="net.gencat.ctti.canigo.services.security. LDAPAuthenticationConfiguration"> <!- Propietats obligatóries -> <property name ="ldapURL" value ="ldap://localhost:389/dc=mycompany,dc=com" /> <property name ="usernameFormat" value ="uid=\{0\},ou=people,dc=mycompany,dc=com" /> <!- Propietats opcionals -> <property name ="userLookupNameFormat" value ="uid=\{0\},ou=people" /> <property name ="roleAttribute" value ="title" /> </bean> _Configuració de la Font d'Autorització per SACE Fitxer de configuració: canigo-services-security.xml En el cas que es requereixi configurar l'autentificació per mitjà de crides directes a SACE podem fer ús d'una classe diferent. Per a realitzar les proves en desenvolupament podem instal- lar un VPN Client per connectar-se al servidor SACE (consultar el document 'Directori Corporatiu de la Generalitat de Catalunya - Guia d'integració d'aplicacions v3.7'). La configuració de l'accés al SACE es fa per mitjà d'un bean de la classe 'net.gencat.ctti.canigo.services.
Exemple:
<bean id="SACEAuthenticationConfiguration" class="net.gencat.ctti.canigo.services.security. SACEAuthenticationConfiguration"> <property name ="urlSACE" value ="https*://sace.prepdc.gencat.intranet/SACE/SACE_Logon.aspx?XMLIn=*"/> <property name ="userNameFormat" value ="NIF"/> </bean> Configuració del Formulari d'Autentificació i la Seqüència d'Autentificació Fitxer de configuració: canigo-services-security.xml Una vegada definides les fonts d'autentificació configurarem quin és el formulari d'autentificació i com ha de realitzar-se l'autentificació, potser en més d'una font. Per exemple, podriem considerar que en primer lloc s'autentifiqui en un esquema de base de dades i si no es troba en aquesta comprovar-ho en un LDAP corporatiu, etc. Per a configurar el formulari i la seqüència es farà ús d'un bean de la classe 'net.gencat.ctti.canigo.services.
Exemple:
<bean id="SACEAuthenticationConfiguration1" ... </bean> <bean id="ldapAuthenticationConfiguration2" ... </bean> <bean id="databaseAuthenticationConfiguration3" ... </bean> <bean id="authenticationConfiguration" class="net.gencat.ctti.canigo.services.security.AuthenticationSecurityConfiguration"> <property name="loginFormUrlValue" value="/login.jsp" /> <property name="authenticationFailureUrlValue" value="/login.jsp" /> <property name="filterProcessesUrl" value="/AppJava/acegiLogon" /> <property name="authenticationProvidersConfigurationList"> <list> <ref local="SACEAuthenticationConfiguration1" /> <ref local="ldapAuthenticationConfiguration2" /> <ref local="databaseAuthenticationConfiguration3" /> </list> </property> </bean> Configuració de l'AutoritzacióFitxer de configuració: canigo-services-security.xml Podem definir l'autorització a 3 nivells:
Configuració de les Autoritzacions d'urls per rol d'usuari L'exemple més normal i el que utilitzarem com a norma general en les nostres aplicacions, és donar accés segons els rols que té l'usuari. La configuració de les autoritzacions d'urls es fa per mitjà de la propietat "secureUrls" del bean de canigo 'authorizationConfiguration'.
Exemple:
<bean id="authorizationConfiguration"class="net.gencat.ctti.canigo.services.security. AuthorizationSecurityConfiguration"> <!-- Propietat opcional per les urls autoritzades --> <property name ="secureUrls"> <value> /**/*read* = ROLE_GESTOR, ROLE_USUARIO /**/*delete* = ROLE_GESTOR /secure/** = ROLE_GESTOR </value> </property> </bean> Configuració de les Autoritzacions a nivell de classe i mètode Per mitjà de proxies dinàmics lligats a aspectes (programació orientada a aspectes) podem configurar que determinats rols no tinguin accés a determinats mètodes de determinades classes.
Exemple:
<bean id="authorizationConfiguration" class="net.gencat.ctti.canigo.services.security. AuthorizationSecurityConfiguration"> <!-- Propietat opcional per les classes i mètodes autoritzats --> <property name="secureBusinessObjects"> <value> com.business.UsersManager = ROLE_GESTOR com.business.CategoryManager.delete = ROLE_GESTOR com.business.CategoryManager.read = ROLE_GESTOR, ROLE_USUARIO </value> </property> </bean> Configuració de les Autoritzacions amb ACLS Hi ha casos en que la protecció de les crides a mètodes no és suficient, necessitant protegir-se de diferent forma diferents instàncies d'una classe. En la majoria de casos, no fa falta cap configuració de fitxers XML. La protecció a les instàncies necessita conéixer quin és l'identificador de la instància. Per defecte es considerarà el mètode 'getId()' de l'objecte. Si no existís aquest mètode podrem configurar quin és el mètode a utilitzar per a obtenir l'identificador de l'objecte. Aquesta configuració es fa en el bean de canigo 'authorizationConfiguration' per mitjà de la propietat "domainObjectsIdGetters":
Exemple:
<bean id="authorizationConfiguration" class="net.gencat.ctti.canigo.services.security. AuthorizationSecurityConfiguration"> <!- Propietat pels getters dels identificadors -> <property name ="domainObjectsIdGetters"> <value>com.business.ComplexDomainObject = getDomainObjectId</value> </property> </bean> Configuració del Servei d'Accés a Informació GeneralEn casos concrets, des del codi voldrem obtenir informació relacionada amb l'usuari connectat. Per aquest objectiu s'ofereix una interfície 'SecurityService'. En l'actualitat s'ofereix una implementació basada en 'Acegi' que podrem utilitzar introduint la següetn configuració:
<bean id="securityService" class="net.gencat.ctti.canigo.services.security.acegi.
SecurityServiceAcegiImpl"/>
En aquest moment, segons la configuració d'injecció de beans (tal i com s'exposa al document de Servei de Configuració) podrem usar el servei des de qualsevol classe de l'aplicació. Utilització del ServeiAutentificació per FormulariHi ha diverses possibilitats d'autentificació des de Web. En aquest apartat ens centrarem en l'autentificació amb formulari (per a més informació consultar la secció '1.10' del tutorial de 'Acegi'). És necessari crear una pàgina en què s'introdueixi l'usuari i el password. Aquesta pàgina ha de complir els requisits següents:
Podem adaptar el codi font següent en les nostres pàgines de Login. El text en negreta i marcat és codi reutilitzable:
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core'%> <%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter"%> <%@ page import="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"%> <%@ page import="net.sf.acegisecurity.AuthenticationException"%> <html> <head> <title>Login</title> </head> <body> <h1>Login</h1> <p><%-- this form-login-page form is also used as the form-error-page to ask for a login again. --%> <c:if test="${not empty param.login_error}"> <font color="red"> Your login attempt was not successful, try again.<BR> <BR> Reason: <%=((AuthenticationException) session .getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)) .getMessage()%> </font> </c:if> <form action="<c:url value='j_acegi_security_check'/>" method="POST"> <table> <tr> <td>User:</td> <td> <input type='text' name='j_username' <c:if test="${not empty param.login_error}"> value='<%=session.getAttribute(AuthenticationProcessingFilter. ACEGI_SECURITY_LAST_USERNAME_KEY) %>' </c:if>> </td> </tr> <tr> <td>Password:</td> <td> <input type='password' name='j_password'> </td> </tr> <tr> <td colspan='2'><input name="submit" type="submit"></td> </tr> </table> </form> </body> </html> Utilització de l'Autorització en les nostres pàgines JSPEn cas de voler presentar determinat contingut depenent dels rols de l'usuari podem fer ús dels tags proporcionats per Acegi. Per a això, seguirem els passos següents:
Des de la versió JSP 1.2 no és necessari configurar en el fitxer 'web.xml' la referència a les llibreries. Podem referenciar directament per mitjà d'una url el jar, tal com es mostra a continuació:
<%@ taglib prefix="authz" uri="http://acegisecurity.sf.net/authz" %>
Una vegada definida la referència a la llibreria i el seu prefix 'authz', podem incorporar el tag a la pàgina JSP per mitjà de '<authz:authorize>', en el que podrem definir els atributs següents:
Exemple:
<authz:authorize ifAllGranted="ROLE_ADMIN"> <td> <A href="del.htm?id=" 123">Borrar</A> </td> </authz:authorize> Per a més informació sobre el tag "authorize", consultar la pàgina http://acegisecurity.sourceforge.net/docbook/acegi.html#N10C28 Obtenció d'Informació de Seguretat amb APIEl servei de seguretat, definit amb el bean 'SecurityService' (tal i com s'explica en l'apartat de Configuració) conté una signatura d'operacions Consultar en el JavaDoc la informació sobre la interfície SecurityService: Gestió dels ACLs mitjançant la APIPer a cada instància de la lògica de negoci podem afegir a la base de dades els permisos per mitjà de l'ús de la interfície 'ACLsDAO': Consultar en el JavaDoc la informació sobre la interfície ACLsDAO: Eines de SuportServidor LDAP de proves: openLDAPEls diferents passos per a instal- lar openLDAP i importar un directori LDAP d'exemple són:
Si tot ha funcionat bé, hauríem de veure una sortida com la següent:
![]()
La contrasenya per defecte és "secret".
JxplorerComprovarem que la importació de dades ha funcionat amb Jxplorer, un client LDAP Java i opensource.
La contrasenya per defecte és "secret". La pantalla següent mostra els valors de la diferents paràmetres:
![]()
ExemplesExemple de configuració d'autentificació amb BBDD, SACE i LDAPEn aquesta part es descriuen 2 dels exemples més comuns d'autentificació:
Exemple de configuració amb autentificació SACE
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="${dataSource.jndiName}"/> </bean> <bean id="SACEAuthenticationConfiguration" class="net.gencat.ctti.canigo.services.security.SACEAuthenticationConfiguration"> <property name="urlSACE" value="https://sace.prepdc.gencat. intranet/SACE/SACE_Logon.aspx?XMLIn=" /> <property name="userNameFormat" value="NIF" /> </bean> <bean id="authenticationConfiguration" class="net.gencat.ctti.canigo.services.security.AuthenticationSecurityConfiguration"> <property name="loginFormUrlValue" value="/login.jsp" /> <property name="authenticationFailureUrlValue" value="/login.jsp" /> <property name="filterProcessesUrl" value="/AppJava/acegiLogin" /> <property name="authenticationProvidersConfigurationList"> <list> <ref local="SACEAuthenticationConfiguration" /> </list> </property> </bean> <bean id="authorizationConfiguration" class="net.gencat.ctti.canigo.services.security.AuthorizationSecurityConfiguration"> <property name="rolesList"> <list> <value>ROLE_ADMIN</value> <value>ROLE_USER</value> </list> </property> <property name="secureUrls"> <value> /**/*.do* = ROLE_USER,ROLE_ADMIN </value> </property> </bean> <import resource="classpath:/spring/acegi-beans.xml" /> </beans> Els beans canigo que usen "Acegi" estan continguts en el jar del servei de seguretat, per la qual cosa haurem d'importar aquest recurs en el nostre "application context" de Spring amb la línia següent:
<import resource="classpath:spring/acegi-beans.xml" /> Autentificació per BBDD amb una BBDD ja existent
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="${dataSource.jndiName}"/> </bean> <bean id="existingDatabaseAuthenticationConfiguration" class="net.gencat.ctti.canigo.services.security.DatabaseAuthenticationConfiguration"> <property name="passwordEncoderClass" value="net.sf.acegisecurity.providers.encoding.PlaintextPasswordEncoder" /> <property name="usersByUserNameQuery" value="SELECT username,password FROM users WHERE username = ?" /> <property name="authoritiesbyUserNameQuery" value="SELECT username, role FROM user_roles WHERE username =?" /> </bean> <bean id="authenticationConfiguration" class="net.gencat.ctti.canigo.services.security.AuthenticationSecurityConfiguration"> <property name="loginFormUrlValue" value="/login.jsp" /> <property name="authenticationFailureUrlValue" value="/login.jsp" /> <property name="filterProcessesUrl" value="/AppJava/acegiLogin" /> <property name="authenticationProvidersConfigurationList"> <list> <ref local=" existingDatabaseAuthenticationConfiguration" /> </list> </property> </bean> <bean id="authorizationConfiguration" class="net.gencat.ctti.canigo.services.security.AuthorizationSecurityConfiguration"> <property name="rolesList"> <list> <value>ROLE_ADMIN</value> <value>ROLE_USER</value> </list> </property> <property name="secureUrls"> <value> /**/*.do* = ROLE_USER,ROLE_ADMIN </value> </property> </bean> <import resource="classpath:/spring/acegi-beans.xml" /> </beans> Exemple de formulari de login amb JSTL i Struts
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter"%> <%@ page import="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"%> <%@ page import="net.sf.acegisecurity.AuthenticationException"%> <style type="text/css"> <%-- this form-login-page form is also used as the form-error-page to ask for a login again. --%> <c:if test="${not empty param.login_error}"> <bean:message key="jsp.login.error" /> </c:if> <bean:message key="jsp.login.message" /> <form action="<c:url value='/AppJava/acegiLogin'/>" method="post"> <table width="100%" border="0"> <tr> <td><bean:message key="jsp.login.user" />:</td> <td><input type='text' name='j_username' <c:if test="${not empty param_error}"> value='<%= session.getAttribute(AuthenticationProcessingFilter. ACEGI_SECURITY_LAST_USERNAME_KEY)%>' </c:if>></td> </tr> <tr> <td><bean:message key="jsp.login.password" />:</td> <td><input type='password' name='j_password'></td> </tr> <tr> <td colspan="2" align="right"><input type="submit" value="<bean:message key="jsp. includes.submit"/>"/></td> </tr> </table> </form> Exemple de configuració d'ACLsVolem donar els permisos "llegir" i "escriure" (READ +WRITE) a un usuari "usuari1" per a la instància de la lògica de negoci "Categoria Papagais". Primer, recollim el DAO de seguretat de canigo:
// Get the DAO from the Spring context ACLsDAO securityDAO = (ACLsDAO) applicationContext.getBean("securityDao"); Segon, recollim la instància de la lògica de negoci "Categoria Papagais" , per mitjà d'un DAO:
// Get the business object using a DAO Category papagayo = CategoryDAO.read("papagayo"); Finalment podem afegir els permisos per a aquesta instància per l'usuari "usuari1":
// Add permissions for user "usuario1" for the papagayo securityDAO.addReadPermission("usuario1", papagayo); securityDAO.addWritePermission("usuario1", papagayo); |