- Spring Security
- Spring Security
Provide declarative security for Spring-based applications using filters.
Handle authentication and authorization from two angles
- web request level and restrict access at the URL
- method invocatino level using Spring AOP(proxying objects and applying advice that ensures that the user has authority to invoke a method)
- Install using Maven. Very easy
- Configuration
Basic configuration of spring-security.xml
<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
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
</beans:beans>
- Securing web request
DelegatingFilterProxy(Servlet Context) --Delegates to --> Spring-Injected filter(Spring Application Context).
- Performed using filters
Spring security looks for a bean called springSecurityFilterChain
in web.xml
<filter>
<filter-name>springSecurityFilterChain</filter-name> <--- this class delegates to a filter resgistered as a bean
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- Configure app-spring.xml
- http://localhost:8080/Spitter/spring_security_login.
Configure to Spring security intercept all URL (/**) and restrict access only to ROLE_TEST
<http auto-config="true" >
<form-login/> |
<http-basic/> | <--- Uses a default login page.
<logout/> |
<intercept-url pattern="/**"access="ROLE_TEST"/> <---- interceptor to url
</http>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/test-servlet.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
HTML - generated by Spring security
<body onload='document.f.j_username.focus();'>
<form name='f'method='POST' action='/Spitter/j_spring_security_check'>
<input type='text'name='j_username'value=''>
<input type='password'name='j_password'/>
<inputname="submit"type="submit"/>
<inputname="reset"type="reset"/>
</form>
- To define a specific page
<form-loginlogin-processing-url="/static/j_spring_security_check"
login-page="/login"
authentication-failure-url="/login?login_error=t"/>
HTML
<%@ taglibprefix="s"uri="http://www.springframework.org/tags"%>
<div>
<spring:urlvar="authUrl" value="/static/j_spring_security_check"/> <-- Authentication filter path
<form method="post"class="signin"action="${authUrl}">
<inputid="username_or_email" name="j_username" type="text" />
<inputid="password" name="j_password" type="password" />
<small><a href="/account/resend_password">Forgot?</a></small>
<inputid="remember_me" name="_spring_security_remember_me" type="checkbox"/>
<td><inputname="commit"type="submit"value="SignIn"/></td>
</form>
<scripttype="text/javascript">
document.getElementById('username_or_email').focus();
</script>
</div>
Most important are j_username and j_password.
- logout
<logout logout-url="/static/j_spring_security_logout"/>
- Intercepting requests
First line of defense in the request-level security.
<intercept-urlpattern="/**"access="ROLE_USER"/> <--- All request is allowed to ROLE_USER
<intercept-urlpattern="/admin/**"access="ROLE_ADMIN"/> /admin/** allowed to ROLE_ADMIN
Rule are top to bottom. Than order of declarations is important
- Securing using Spring Expression (SpEL)
To enable:
<http auto-config="true"use-expressions="true">
...
</http>
<intercept-urlpattern="/admin/**"access="hasRole('ROLE_ADMIN')"/> <--- hasRole if user has granted the ROLE_ADMIN
Security Expressions
authentication, denyAll, hasAnyRole(LIST), hasRole, hasIpAddress(IP Address), isAnonimous(), isAuthenticated() ,
isFullyAuthenticated(), isRememberMe(), permitAll, principal
Ex:
<intercept-urlpattern="/admin/**" access="hasRole('ROLE_ADMIN') and hasIpAddress('192.168.1.2')"/>
- Forcing request to HTTPS
- Sure. Sensitive information should be passed encrypted over HTTPS
<intercept-urlpattern="/project/form"requires-channel="https"/> <--- Redirect automatically to a https channel
<intercept-urlpattern="/home"requires-channel="http"/>
- Example
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/logout" access="permitAll" />
<intercept-url pattern="/accessdenied" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login" default-target-url="/list" authentication-failure-url="/accessdenied" />
<logout logout-success-url="/logout" />
</http>
- Securing view-level elements
Securing in view layer.
<%@ taglibprefix="security" uri="http://www.springframework.org/security/tags"%>
Elements:
- <security:accesscontrollist> : allow the body of this tag to be rendered if the current authenticated user has permition
- <security:authorize> : Allows the body of this tag to be rendered if a meet a specific security constraint
<security:authorizeaccess="hasRole('ROLE_SPITTER')">
Render something
</security:authorize>
or
<security:authorize access="isAuthenticated() and principal.username=='habuma'">
<a href="/admin">Administration</a>
</security:authorize>
Other parameters
- access
- url: The the url is allowad to some user
- ifAllGranted
- ifAnyGranted
- ifNotGranted
- <security:authentication> : Accesses properties of the current user's authentication object
Hello <security:authentication property="principal.username"/>
<security:authentication property="principal.username" var="loginId"/>
Access the prop of principal(object).
Can use: authorities(collection of GrandAuthorities), credentials(ex:password), details(additional info like IP, session ID), principal(principal's user)
- Authenticating Users
Spring supports authenticating using, but you can implements your own
- In-memory, JDBC-based, LDAP-based user repositories, OpenID decentralized user identity systems, X509 certificates, JASS-based providers
- In-memory user repository
configure in spring-security.xml. Hard coded
<user-serviceid="userService">
<user name="habuma"password="letmein" authorities="ROLE_SPITTER,ROLE_ADMIN"/>
<user name="twoqubed"password="longhorns" authorities="ROLE_SPITTER"/>
<user name="admin"password="admin" authorities="ROLE_ADMIN"/>
</user-service>
<security:authentication-manager> <-- Registers the authentication manager(instance of ProviderManager)
<authentication-provider user-service-ref="userService"/>
</security:authentication-manager>
- Using DataBase(JDBC)
wires jdbc-user-service into <authentication-provider>'s user-service-ref, like above
<jdbc-user-service id="userService" data-source-ref="dataSource"/>
This objects uses this to get information: select username,password,enabled from users where username=?
to look up authorities: select username,authority from authorities where username=?
Whole example changing the database:
<jdbc-user-service id="userService"
data-source-ref="dataSource" <---- Reference to the dataSource
users-by-username-query="select username,password,true from testTable where username=?" <-- to select user
authorities-by-username-query="select username, authority from testTable where username=?"/> <-- Get Authorities
If we dont have authorities your can replace "authority" by 'ROLE_TEST'
- Securing Method-level
Is packed in <global-method-security>
ex: <global-method-security secured-annotations="enabled"/>
Four Ways:
- method annotated @Secured
@Secured("ROLE_USER", "ROLE_ADMIN")
public void addSpittle(Spittle spittle){
// ...
}
- Method annotated with JSR-250 - @RollesAllowed
Used identically as @Secured. Difference is that @RollesAllowed is standard java
- <global-method-securityjsr250-annotations="enabled"/>
- Method annotated with Spring's pre and post invocation
- Uses SpEL. More powerful than previous.
- <global-method-securitypre-post-annotations="enabled"/>
- Annotations
@PreAuthorize Restricts access to a method before invocation based on the result of evaluating an expression
@PreAuthorize("(hasRole('ROLE_USER')and#spittle.text.length()<=140) or hasRole('ROLE_PREMIUM')")
public void add Spittle(Spittle spittle){
// ...
}
@PostAuthorize Allows a method to be invoked, but throws a security exception if the expression evaluates to false
@PostAuthorize("returnObject.spitter.username==principal.username")
public Spittle getSpittleById(longid){
// ...
}
@PreFilter Allows a method to be invoked, but filters input prior to entering the method
@PreAuthorize("hasRole('ROLE_SPITTER)")
@PostFilter("filterObject.spitter.username==principal.name")
public List<Spittle>getABunchOfSpittles(){
...
}
@PostFilter Allows a method to be invoked, but filters the results of that method per an expression
- Method matching some explicity declared pointcuts
Nenhum comentário:
Postar um comentário