SEC-278: Initial commit of tutorial sample.
This commit is contained in:
parent
dab4792b5b
commit
da187147f2
|
@ -2035,7 +2035,7 @@ if (obj instanceof UserDetails) {
|
|||
|
||||
<para>Most JAAS <literal>LoginModule</literal>s require a callback
|
||||
of some sort. These callbacks are usually used to obtain the
|
||||
username and password from the user. </para>
|
||||
username and password from the user.</para>
|
||||
|
||||
<para>In an Acegi Security deployment, Acegi Security is responsible
|
||||
for this user interaction (via the authentication mechanism). Thus,
|
||||
|
@ -2079,7 +2079,7 @@ if (obj instanceof UserDetails) {
|
|||
principal, and multiple <literal>GrantedAuthority</literal>[]s. To
|
||||
facilitate mapping between these different concepts, Acegi
|
||||
Security's JAAS package includes an
|
||||
<literal>AuthorityGranter</literal> interface. </para>
|
||||
<literal>AuthorityGranter</literal> interface.</para>
|
||||
|
||||
<para>An <literal>AuthorityGranter</literal> is responsible for
|
||||
inspecting a JAAS principal and returning a
|
||||
|
@ -5955,6 +5955,51 @@ END;
|
|||
if you're ambitious: try <literal>client _cas_stateless_
|
||||
YOUR-SERVICE-TICKET-ID</literal>.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="tutorial-sample">
|
||||
<title>Tutorial Sample</title>
|
||||
|
||||
<para>Whilst the <link linkend="contacts-sample">Contacts
|
||||
Sample</link> is quite advanced in that illustrates the more powerful
|
||||
features of domain object access control lists and so on, sometimes
|
||||
you just want to start with a nice basic template. The tutorial sample
|
||||
is intended to provide this initial base.</para>
|
||||
|
||||
<para>The compiled tutorial is included in the distribution ZIP file,
|
||||
ready to be deployed into your web container. Authentication is
|
||||
handled by the <link
|
||||
linkend="dao-provider">DaoAuthenticationProvider</link>, using the
|
||||
<link linkend="in-memory-service">in-memory</link>
|
||||
<literal>UserDetailsService</literal> that sources information from
|
||||
the <literal>users.properties</literal> file located in the WAR's
|
||||
<literal>/WEB-INF</literal> directory. The <link
|
||||
linkend="form">form-based</link> authentication mechanism is used,
|
||||
with the commonly-used <link linkend="remember-me">remember-me</link>
|
||||
authentication provider used to automatically remember the login using
|
||||
cookies.</para>
|
||||
|
||||
<para>In terms of authorization, to keep things simple we've
|
||||
configured the tutorial to only perform some basic <link
|
||||
linkend="filter-invocation-authorization">web filter
|
||||
authorization</link>. We've wired two common <link
|
||||
linkend="pre-invocation">pre-invocation access decision voters</link>,
|
||||
being the <literal>RoleVoter</literal> and
|
||||
<literal>AuthenticatedVoter</literal>, such that
|
||||
<literal>ROLE_*</literal> configuration attributes and
|
||||
<literal>IS_AUTHENTICATED_*</literal> configuration attributes may be
|
||||
used. Of course, it's extremely easy to add in other providers, with
|
||||
most users probably starting with some services-layer security using
|
||||
<link linkend="aop-alliance">MethodSecurityInterceptor</link>.</para>
|
||||
|
||||
<para>We recommend you start with the tutorial sample, as the XML is
|
||||
minimal and easy to follow. All of the needed <link
|
||||
linkend="filters">filters</link> are configured properly, and using
|
||||
best practise. Most importantly, you can easily this one XML file (and
|
||||
its corresponding <literal>web.xml</literal> entries) to your existing
|
||||
application. Only when this basic integration is achieved do we
|
||||
suggest you attempt adding in method authorization or domain object
|
||||
security.</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="community">
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
maven.multiproject.type=war
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project>
|
||||
<extend>${basedir}/../project.xml</extend>
|
||||
<pomVersion>3</pomVersion>
|
||||
<artifactId>acegi-security-sample-tutorial</artifactId>
|
||||
<name>Acegi Security System for Spring - Tutorial sample</name>
|
||||
<siteDirectory>/home/groups/a/ac/acegisecurity/htdocs/multiproject/acegi-security-sample-tutorial</siteDirectory>
|
||||
<repository>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</connection>
|
||||
<developerConnection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</developerConnection>
|
||||
<url>http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/samples/tutorial/</url>
|
||||
</repository>
|
||||
</project>
|
|
@ -0,0 +1,148 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- A simple "base bones" Acegi Security configuration.
|
||||
-
|
||||
- The sample includes the "popular" features that people tend to use.
|
||||
- Specifically, form authentication, remember-me, and anonymous processing.
|
||||
- Other features aren't setup, as these can be added later by inserting
|
||||
- the relevant XML fragments as specified in the Reference Guide.
|
||||
-
|
||||
- To assist new users, the filters specified in the FilterChainProxy are
|
||||
- declared in the application context in the same order. Collaborators
|
||||
- required by those filters are placed at the end of the file.
|
||||
-
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
|
||||
<property name="filterInvocationDefinitionSource">
|
||||
<value>
|
||||
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||
PATTERN_TYPE_APACHE_ANT
|
||||
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
|
||||
|
||||
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
|
||||
<constructor-arg value="/index.jsp"/> <!-- URL redirected to after logout -->
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<ref bean="rememberMeServices"/>
|
||||
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="authenticationFailureUrl" value="/acegilogin.jsp?login_error=1"/>
|
||||
<property name="defaultTargetUrl" value="/"/>
|
||||
<property name="filterProcessesUrl" value="/j_acegi_security_check"/>
|
||||
<property name="rememberMeServices" ref="rememberMeServices"/>
|
||||
</bean>
|
||||
|
||||
<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>
|
||||
|
||||
<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="rememberMeServices" ref="rememberMeServices"/>
|
||||
</bean>
|
||||
|
||||
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
|
||||
<property name="key" value="changeThis"/>
|
||||
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
|
||||
</bean>
|
||||
|
||||
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
|
||||
<property name="authenticationEntryPoint">
|
||||
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
|
||||
<property name="loginFormUrl" value="/acegilogin.jsp"/>
|
||||
<property name="forceHttps" value="false"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="accessDeniedHandler">
|
||||
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
|
||||
<property name="errorPage" value="/accessDenied.jsp"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager">
|
||||
<bean class="org.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions" value="false"/>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<bean class="org.acegisecurity.vote.RoleVoter"/>
|
||||
<bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||
PATTERN_TYPE_APACHE_ANT
|
||||
/secure/extreme/**=ROLE_SUPERVISOR
|
||||
/secure/**=IS_AUTHENTICATED_REMEMBERED
|
||||
/**=IS_AUTHENTICATED_ANONYMOUSLY
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
|
||||
<property name="userDetailsService" ref="userDetailsService"/>
|
||||
<property name="key" value="changeThis"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="daoAuthenticationProvider"/>
|
||||
<bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
|
||||
<property name="key" value="changeThis"/>
|
||||
</bean>
|
||||
<bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
|
||||
<property name="key" value="changeThis"/>
|
||||
</bean>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
||||
<property name="userDetailsService" ref="userDetailsService"/>
|
||||
<property name="userCache">
|
||||
<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
|
||||
<property name="cache">
|
||||
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
|
||||
<property name="cacheManager">
|
||||
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
|
||||
</property>
|
||||
<property name="cacheName" value="userCache"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- UserDetailsService is the most commonly frequently Acegi Security interface implemented by end users -->
|
||||
<bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
|
||||
<property name="userProperties">
|
||||
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
|
||||
<property name="location" value="/WEB-INF/users.properties"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
|
||||
<bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,18 @@
|
|||
# Global logging configuration
|
||||
log4j.rootLogger=WARN, stdout, fileout
|
||||
|
||||
log4j.logger.org.acegisecurity=DEBUG, stdout, fileout
|
||||
|
||||
# Console output...
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.conversionPattern=[%p,%c{1},%t] %m%n
|
||||
|
||||
# Rolling log file output...
|
||||
log4j.appender.fileout=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.fileout.File=contacts.log
|
||||
#log4j.appender.fileout.File=${webapp.root}/WEB-INF/log4j.log
|
||||
log4j.appender.fileout.MaxFileSize=1024KB
|
||||
log4j.appender.fileout.MaxBackupIndex=1
|
||||
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p %c{1},%t:%L - %m%n
|
|
@ -0,0 +1,4 @@
|
|||
marissa=koala,ROLE_SUPERVISOR
|
||||
dianne=emu,ROLE_USER
|
||||
scott=wombat,ROLE_USER
|
||||
peter=opal,disabled,ROLE_USER
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>
|
||||
|
||||
<!--
|
||||
- Contacts web application
|
||||
-
|
||||
- web.xml for "filter" artifact only.
|
||||
-
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<web-app>
|
||||
|
||||
<display-name>Acegi Security Tutorial Application</display-name>
|
||||
|
||||
<!--
|
||||
- Location of the XML file that defines the root application context
|
||||
- Applied by ContextLoaderListener.
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/applicationContext-acegi-security.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
<filter>
|
||||
<filter-name>Acegi Filter Chain Proxy</filter-name>
|
||||
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
<init-param>
|
||||
<param-name>targetClass</param-name>
|
||||
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Filter Chain Proxy</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!--
|
||||
- Loads the root application context of this web app at startup.
|
||||
- The application context is then available via
|
||||
- WebApplicationContextUtils.getWebApplicationContext(servletContext).
|
||||
-->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
</web-app>
|
|
@ -0,0 +1,16 @@
|
|||
<%@ page import="org.acegisecurity.context.SecurityContextHolder" %>
|
||||
<%@ page import="org.acegisecurity.Authentication" %>
|
||||
<%@ page import="org.acegisecurity.ui.AccessDeniedHandlerImpl" %>
|
||||
|
||||
<h1>Sorry, access is denied</h1>
|
||||
|
||||
|
||||
<p>
|
||||
<%= request.getAttribute(AccessDeniedHandlerImpl.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY)%>
|
||||
|
||||
<p>
|
||||
|
||||
<% Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (auth != null) { %>
|
||||
Authentication object as a String: <%= auth.toString() %><BR><BR>
|
||||
<% } %>
|
|
@ -0,0 +1,45 @@
|
|||
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
|
||||
<%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %>
|
||||
<%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %>
|
||||
<%@ page import="org.acegisecurity.AuthenticationException" %>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Login</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Login</h1>
|
||||
|
||||
<P>Valid users:
|
||||
<P>
|
||||
<P>username <b>marissa</b>, password <b>koala</b> (supervisor)
|
||||
<P>username <b>dianne</b>, password <b>emu</b> (normal user)
|
||||
<p>username <b>scott</b>, password <b>wombat</b> (normal user)
|
||||
<p>username <b>peter</b>, password <b>opal</b> (user disabled)
|
||||
<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><input type="checkbox" name="_acegi_security_remember_me"></td><td>Don't ask for my password for two weeks</td></tr>
|
||||
|
||||
<tr><td colspan='2'><input name="submit" type="submit"></td></tr>
|
||||
<tr><td colspan='2'><input name="reset" type="reset"></td></tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>Home Page</h1>
|
||||
Anyone can view this page.
|
||||
|
||||
<p><a href="secure/index.jsp">Secure page</a>
|
||||
<p><a href="secure/extreme/index.jsp">Extremely secure page</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>VERY Secure Page</h1>
|
||||
This is a protected page. You can only see me if you are a supervisor.
|
||||
|
||||
<p><a href="../../">Home</a>
|
||||
<p><a href="../../j_acegi_logout">Logout</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>Secure Page</h1>
|
||||
This is a protected page. You can get to me if you've been remembered,
|
||||
or if you've authenticated this session.
|
||||
|
||||
<p><a href="../">Home</a>
|
||||
<p><a href="../j_acegi_logout">Logout</a>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue