# Security bei Spring?



## internet (3. Nov 2009)

Hallo, 
ich wollte mal nachfragen, wie man bei Spring die Security realsieren kann. 
Also, dass zum Beispiel nur User mit bestimmter Rolle die Methode ausführen können.

userInRole gibt es ja bei den Richfaces!
Und bei EJB gibt es eben auch diverse Annotationen. 
Wie macht man dies mit Spring?


----------



## FArt (4. Nov 2009)

Spring Security


----------



## MQue (4. Nov 2009)

FArt hat gesagt.:


> Spring Security



Bin auch gerade beim durchackern von Spring Security (Doku Seite 5). Was mir nicht ganz klar ist sind die Namespaces? Für was brauche ich diese?



```
The namespace is designed to capture the most common uses of the framework and provide a simplified and
concise syntax for enabling them within an application.
```

Diesen Satz kappier ich nicht ganz wobei ich auch sagen muss, dass mir noch der Überblick fehlt.
Die ganze Konfiguration von Spring ist ja in <beans>...</beans> eingebettet, das versteh ich momentan unter Namespace!?

PS: Was mir noch nicht ganz klar ist, ist das Konfigurieren des filters in web.xml:


```
<filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
```

Wenn ich das so machen bekomme ich die Exception:


```
SCHWERWIEGEND: Exception starting filter springSecurityFilterChain
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' is defined
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:971)
```

ich hab jetzt keine Anhnung was ich in applicationContext.xml reinschreiben muss, mir ist klar, dass es eine bean mit der id springSecurityFilterChain sein muss, aber was muss das für eine Klasse sein?

und noch was, aus der Spring Security doku geht nicht klar hervor, wo man


```
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
```
hinschreiben muss? in web.xml oder applicationContext.xml oder in eine jsp - ich hab keine Ahnung?

vielen Dank für Hilfe,
lg


----------



## MQue (5. Nov 2009)

So, bin durchgestiegen, jetzt im nachhinein ist alles klar, deshalb bitte meine blöden Fragen vom vorigen Post ignorieren.
lg


----------



## FArt (5. Nov 2009)

Michael1234 hat gesagt.:


> deshalb bitte meine blöden Fragen vom vorigen Post ignorieren.
> lg


... schon passiert ;-)


----------



## internet (6. Nov 2009)

Könntest du das vielleicht ein wenig zusammenfassen:

Ich brauche zB so etwas, dass man deklarieren, welche Rollen eine Methode ausführen dürfen in der Weboberfläche. 

Und welche Rollen welche Webseite aufrufen / angezeigt bekommen. 
zB ein Gast soll / darf nicht die Webseiten sehen, die ein Admin aufrufen kann, durch die URL einfach abändern. Sprich der Gast sieht wie die URL aussieht, und gibt einfach mal im Browser die URL statt "user" -> "admin" ein. 
BSP

Admin
domain/admin/user.jsf

Gast: 
domain/user/user.jsf

Wäre sehr nett, wenn du mir ein wenig Hilfe leisten könntest, ohne, dass ich 1000 Seiten durchlesen muss =)


----------



## FArt (9. Nov 2009)

Ja, leider könnte das in Arbeit ausarten.
Tipp: Google mit den Suchworten "tutorial spring security"


----------



## moloch (19. Mai 2010)

hallo,
gibt es denn zum thema nicht mal eine schritt für schritt anleitung von einem kleinen beispiel?


----------



## pizza1234 (20. Mai 2010)

Hi,
was ist denn an der Doku auf der Springseite so schlecht?Da ist doch wirklich alles vorhanden, was man braucht!
Und in den jars von Spring Security gibt es auch 2 Beispiele!

Grüße
Peter


----------



## internet (21. Jun 2010)

ich möchte vorerst nur meine URL schützen.
Wie kann ich das einfach realisieren?

In den Beispielen habe ich immer wieder gesehen, dass dort mehrere Benutzernamen und dessen Passwort in der web.xml steht. 
Ich greife allerdings diese Daten von meiner Datenbank ab.
Wie mache ich das dann?

Ich habe in meiner DB eine Tabelle "benutzer", wo auch das Passwort hinterlegt ist.
Und auch eine Tabelle "rolle".

Kann mir bitte jemand weiterhelfen.


----------



## pizza1234 (21. Jun 2010)

Hi,

einmal hier: 2.2.3 Using other Authentication Providers

und deine Tabellen müssen so aussehen: 

```
create table users(
      username varchar_ignorecase(50) not null primary key,
      password varchar_ignorecase(50) not null,
      enabled boolean not null);

  create table authorities (
      username varchar_ignorecase(50) not null,
      authority varchar_ignorecase(50) not null,
      constraint fk_authorities_users foreign key(username) references users(username));
      create unique index ix_auth_username on authorities (username,authority);
```

Das steht aber alles in der Spring-Doku....

Grüße
Peter


----------



## internet (21. Jun 2010)

müssen die Tabellen / Attribute genauso heißen?
Können diese Tabellen auch zusätzliche Attribute beinhalten?
Oder geht auch das hier: (RACF = Benutzername)


```
CREATE TABLE IF NOT EXISTS rolle(
	rolle_id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
	rolle_auswahl NVARCHAR(20) NOT NULL,
	bemerkung NVARCHAR(50),
	emailadresse_1 NVARCHAR(50) NOT NULL,
	emailadresse_2 NVARCHAR(50)
);


CREATE TABLE IF NOT EXISTS benutzer(
	benutzer_id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
	passwort NVARCHAR(128) NOT NULL,
	zugang_erlaubt boolean NOT NULL,
	freigeschaltet boolean NOT NULL,
	person_fk BIGINT NOT NULL,
	rolle_fk BIGINT,
	FOREIGN KEY (person_fk) REFERENCES person(person_id),
	FOREIGN KEY (rolle_fk) REFERENCES rolle(rolle_id)
);


CREATE TABLE IF NOT EXISTS person(
	person_id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
	vorname NVARCHAR(32) NOT NULL, 
	nachname NVARCHAR(32) NOT NULL,
	email NVARCHAR(50),
	racf NVARCHAR(7),
);
```


----------



## pizza1234 (22. Jun 2010)

Hi,



> müssen die Tabellen / Attribute genauso heißen?


Nein, du mußt dann aber deinen Provider anpassen. Bei mir sieht das dann so aus:
[XML]	
<security:jdbc-user-service id="authenticationDAO" 
		data-source-ref="dataSource" 
		authorities-by-username-query="SELECT username, role.name AS authority FROM user, `role`, user_role WHERE user.id = user_role.user_id  AND role.id = user_role.role_id AND user.username = ?"
		users-by-username-query="SELECT username ,password ,active AS enabled FROM user WHERE username = ?"/>
[/XML]
Wichtig ist, das natürlich irgendwo in deiner Tabelle die geforderten Attribute auftauchen..




> Können diese Tabellen auch zusätzliche Attribute beinhalten?


Ja. kein Problem!

Grüße,
Peter


----------



## internet (22. Jun 2010)

wie sehen deine Tabellen aus?
Welche Werte haben diese? (Insbesonderen die Werte der Rollen interessieren mich)


----------



## pizza1234 (22. Jun 2010)

Hi,


```
CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(200) collate latin1_general_ci default NULL,
  `surname` varchar(200 collate latin1_general_ci default NULL,
  `username` varchar(200) collate latin1_general_ci default NULL,
  `password` varchar(200) collate latin1_general_ci default NULL,
  `active` tinyint(1) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci  ;
  
  
CREATE TABLE IF NOT EXISTS `user_role` (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
  
  CREATE TABLE IF NOT EXISTS `role` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(200) collate latin1_general_ci default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci  ;
```

ROLE_USER,ROLE_XYZ,..

Grüße
Peter


----------



## internet (22. Jun 2010)

ok, vielen Dank. 
Du hast dann eine *n:m Beziehung* zwischen Benutzer und Rollen?
Also ein Benutzer kann mehrere Rollen haben (macht für mich kein Sinn)
Und eben eine Rolle kann mehrere Benutzer haben?


Wie sieht denn deine *Login - Methode* aus?


----------



## pizza1234 (22. Jun 2010)

Hi,



> Also ein Benutzer kann mehrere Rollen haben (macht für mich kein Sinn)


Wieso nicht? Ein Benutzer kann zb. ein Abteilungsleiter und gleichzeitig auch ein Administrator sein!
Hier ist ein guter Artikel dazu.

Login-Methode gibt es nicht, alles weitere wird in der context.xml konfiguriert!

Grüße
Peter


----------



## internet (22. Jun 2010)

Vielen Dank für den Artikel. Ist echt super.

Kannst du die context.xml bitte hier posten. 
Wie sieht der Login / Logout - Button/Link bei dir auf der JSF- Seite aus?


----------



## pizza1234 (23. Jun 2010)

Hi,

leider kann ich dir die context.xml nicht zeigen. Ich benutze aber sowieso kein JSF sondern Spring MVC, insofern würde es dir, glaube ich, auch nichts bringen. Aber eigentlich steht das Wesentliche in der  context.xml doch auch schon hier auf der Seite...

Grüße
Peter


----------



## internet (23. Jun 2010)

Naja, aber ich benötige doch eine LoginBean?

Bzw. eine Login - Methode?

Wie sollte ich mich sonst einloggen auf der Startseite o.Ä.?


----------



## pizza1234 (23. Jun 2010)

Hi,

schau mal hier und hier ! (Ist leider etwas älter!)

Die LoginBean muss deinen Benutzernamen(j_username) und dein Passwort(j_password) enthalten und deine action muss an "j_spring_security_check" redirecten.

Den Rest übernimmt dann ja Spring für dich.

Grüße
Peter


----------



## internet (23. Jun 2010)

OK:
hier meine context:
Passt die Query so mit den obengeschriebenen Tabellen?


=> Ich bekomme aber in der Methode immer eine NULLPOINTER EXCEPTION

*Hier krachts: Authentication result = am.authenticate(request);*



```
<?xml version="1.0" encoding="UTF-8"?>

<!--
  - Sample namespace-based configuration
  -
  -->

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans [url]http://www.springframework.org/schema/beans/spring-beans-3.0.xsd[/url]
                        [url=http://www.springframework.org/schema/security]Index of /schema/security[/url] http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <global-method-security pre-post-annotations="enabled">
        <!-- AspectJ pointcut expression that locates our "post" method and applies security that way
        <protect-pointcut expression="execution(* bigbank.*Service.post*(..))" access="ROLE_TELLER"/>
        -->
    </global-method-security>


    <http use-expressions="true">
        <!-- <intercept-url pattern="/admin/**" 						access="hasRole('ROLE_ADMIN')"/>--> 
         <intercept-url pattern="/admin/**" 									access="ROLE_ADMIN"/> 
        <intercept-url pattern="/personenverwaltung/**" 						access="ROLE_ADMIN"/>
        <intercept-url pattern="/personenverwaltung/createPerson.xhtml" 		access="ROLE_ADMIN"/>
        <intercept-url pattern="/secure/**" 									access="isAuthenticated()" />
        
        <!-- Disable web URI authorization, as we're using <global-method-security> and have @Secured the services layer instead
        <intercept-url pattern="/listAccounts.html" access="isRememberMe()" />
        <intercept-url pattern="/post.html" access="hasRole('ROLE_TELLER')" />
        -->
        <!-- <intercept-url pattern="/**" access="permitAll" /> -->
        
		<form-login
			login-processing-url="/j_spring_security_check"
			login-page="/index.xhtml"
			default-target-url="/admin/index.xhtml"
			authentication-failure-url="/index.xhtml" />
        <logout 	logout-success-url="/index.xhtml"/>
        <remember-me />
		
		<!-- Uncomment to enable X509 client authentication support <x509 /> -->
        
        
        <!-- Uncomment to limit the number of sessions a user can have 
        <session-management invalid-session-url="/faces/common/timeout.xhtml">
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
        </session-management>
        -->
    </http>

	
	

	
	

     <authentication-manager>  
         <authentication-provider>  
             <jdbc-user-service 
	             data-source-ref="dataSource"
	             authorities-by-username-query="SELECT person.racf AS username, rolle.rolle_auswahl AS authority FROM person, `role`, rolle WHERE rolle.id = benutzer.rolle_fk AND person.id = benutzer.person_fk AND person.racf = ?" 
	             users-by-username-query="SELECT person.racf AS username, benutzer.passwort AS password ,active AS enabled FROM person, benutzer WHERE person.racf = ?"/>  
         </authentication-provider>  
     </authentication-manager>  
</beans:beans>
```


und hier die Login - Methode


```
public String login() {
        try {
            Authentication request = new UsernamePasswordAuthenticationToken(this.getRacf(), getPassword());
            Authentication result = am.authenticate(request);
            SecurityContextHolder.getContext().setAuthentication(result);

        } catch (AuthenticationException e) {
            
			createFacesMessage(MESSAGES_BENUTZERVERWALTUNG,
					"einloggen.failedRacf",
					"formLoginEingabe:racf",
					SEVERITY_ERROR);
			return null;
        }
        return "/admin/index";
    }
```


----------



## pizza1234 (23. Jun 2010)

Hi,

wo ist denn deine "dataSource", ist die in einer anderen context.xml? Leider weiß ich nicht, wie das bei JSF geht, aber der Login-Kram wird dir vollständig von Spring abgenommen, du brauchst keine LoginMethode! Schau dir mal oder debug mal im SourceCode die Klasse "AuthenticationProcessingFilter" von Spring Security. Hier


----------



## internet (23. Jun 2010)

die ist in der jpa.xml

Oder muss ich diese auch in der context von springsecurity machen?
Bzw. muss ich diese irgendwie "verlinken" / in der context von springsecurity angeben?


----------



## pizza1234 (23. Jun 2010)

Nein, mußt du nicht verlinken, wenn du sie in der web.xml in "contextConfigLocation" stehen hast.


----------



## internet (23. Jun 2010)

Ja, das steht dort drin.

Solangsam hab ich den Faden verloren, zudem ich das meiste nur über Spring Security 2.0 oder 2.5 finde und auch JSF 1.2

Over the Edge: JSF 2.0 with Spring 3 and Spring Security 3 on Google Application Engine

steht das wiederum, dass man eine LoginBean braucht.
Im Grunde möchte ich nur 2 Dinge realisieren: 
- URL Sperre
- Login

Das sollte doch nicht so schwer sein????:L


----------



## pizza1234 (23. Jun 2010)

..das mit der LoginBean liegt wahrscheinlich eher an JSF als an Spring-Security. Abgesehen davon würde ich nicht unbedingt ein GAE-Besipiel als Referenz nehmen, da dort einige Dinge komplett anders laufen. Du hast dir mit Spring Security und JSF halt zwei nicht triviale Technologien ins Haus geholt. Ich kann dir halt zu JSF nix sagen...


----------



## internet (23. Jun 2010)

ok, lassen wir das login mal außen vor.

Das Sperren von URL muss ja auch so gehen, das hat ja nichts mit JSF zu tun?

[XML]<intercept-url pattern="/admin/**" 	access="ROLE_ADMIN"/> [/XML]

heißt doch: dass alle Seiten, die im Ordner "admin" nur die Rolle "ROLE_ADMIN" sehen können, richtig?
ROLE_ADMIN ist ein Wert in der Tabelle Rolle in der Spalte (bei mir rolle_auswahl)?

Leider funktioniert das auch noch nicht.
Hast du dir die Query mal angeschaut? Ist das so korrekt?


----------



## pizza1234 (24. Jun 2010)

Hi,

müßte es nicht so heißen?Versuch doch deine Querys mal mit Hibernate Tools auszuführen, da kannst du HQL-Abfragen testen.

```
authorities-by-username-query="SELECT person.racf, rolle.rolle_auswahl AS authority FROM person, `role`, rolle WHERE rolle.id = benutzer.rolle_fk AND person.id = benutzer.person_fk AND person.racf = ?"
```


```
users-by-username-query="SELECT person.racf , benutzer.passwort  ,active AS enabled FROM person, benutzer WHERE person.racf = ?"/>
```



> heißt doch: dass alle Seiten, die im Ordner "admin" nur die Rolle "ROLE_ADMIN" sehen können, richtig?


Richtig!

Ich empfehle dir aber trotzdem, dich mal hinzusetzen und die Spring-Security-Doku durchzulesen, dir die Beispiele anzuschauen und dich mit dem Thema ausführlich zu befassen, weil eine falsche Konfiguration der Authentifizierung/Authorisierung unter Umständen schlimmer sein kann, als gar keine!


Grüße
Peter


----------



## internet (24. Jun 2010)

diese query bei 	authorities-by-username-query:
ist das SQL oder HQL ?


----------



## pizza1234 (24. Jun 2010)

Oh Sorry, ist natürlich SQL! Hab ich schon so lange nicht mehr benutzt.....


----------



## internet (25. Jun 2010)

So ich habe es nun hinbekommen, dass ich (teilweise) die Seite schützen kann. 
        Jetzt habe ich allerdings ein Problem beim Login. 
        Wenn ich richtigen Benutzername (RACF) und Passwort eintrage, dann werde ich auf die Seite
        loginError.xhtml umgeleitet. 
        Wenn ich mich falsch einlogge auf die Seite j_spring_security_check. 
        Allerdings heißt es dann, dass es die Seite nicht geben würde.

        Ist die Definition so richtig:
        login-page = Seite wo das Login Formular ist
        default-target-url= Ziel nach einloggen
        authentication-failure-url = Seite wenn ein Fehler auftritt

        Aber was login-processing-url weiß ich nicht so genau!
        Weißt du das?
        Hier mal:


```
<form-login
			login-processing-url="/faces/j_spring_security_check"
			login-page="/faces/index.xhtml"
			default-target-url="/faces/index.xhtml"
			authentication-failure-url="/faces/common/loginError.xhtml" />
```


----------

