Вернуться в список

Введение в Spring Security. Hello World!

Этой статьей начинается серия статей об Spring Security - Java-фреймворк безопасности, который широко используется Spring-сообществом, главным образом в веб.

Spring Security это Java/Java EE фреймворк, предоставляющий механизмы построения систем аутентификации и авторизации, а также другие возможности обеспечения безопасности для промышленных приложений, созданных с помощью Spring Framework. Проект был начат Беном Алексом (Ben Alex) в конце 2003 года под именем «Acegi Security» и был публично представлен под лицензией Apache License в марте 2004. Впоследствии был включён в Spring как официальный дочерний проект. Впервые публично представлен под новым именем Spring Security 2.0.0 в апреле 2008 года, что включило официальную поддержку и подготовку от SpringSource.

В первую очередь добавим зависимости в pom.xml для подключения библиотек Spring Security:

<!-- Spring Security -->
<dependency>
    <groupid>org.springframework.security</groupid>
    <artifactid>spring-security-core</artifactid>
    <version>3.1.0.RELEASE</version>
</dependency>

<dependency>
    <groupid>org.springframework.security</groupid>
    <artifactid>spring-security-web</artifactid>
    <version>3.1.0.RELEASE</version>
</dependency>

<dependency>
    <groupid>org.springframework.security</groupid>
    <artifactid>spring-security-config</artifactid>
    <version>3.1.0.RELEASE</version>
</dependency>

pom.xml

<?xml version ="1.0" encoding ="UTF-8"?>
<project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemalocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupid>com.seostella</groupid>
    <artifactid>springsecuritybasics</artifactid>
    <name>spring-security-basics</name>
    <packaging>war</packaging>
    <version>1.0.0-BUILD-SNAPSHOT</version>
    <properties>
        <java-version>1.6</java-version>
        <org.springframework-version>3.1.0.RELEASE</org.springframework-version>
        <org.aspectj-version>1.6.9</org.aspectj-version>
        <org.slf4j-version>1.5.10</org.slf4j-version>
    </properties>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-context</artifactid>
            <version>${org.springframework-version}</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupid>commons-logging</groupid>
                    <artifactid>commons-logging</artifactid>
                 </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-webmvc</artifactid>
            <version>${org.springframework-version}</version>
        </dependency>
          
        <!-- Spring Security -->
        <dependency>
            <groupid>org.springframework.security</groupid>
            <artifactid>spring-security-core</artifactid>
            <version>${org.springframework-version}</version>
        </dependency>

        <dependency>
            <groupid>org.springframework.security</groupid>
            <artifactid>spring-security-web</artifactid>
            <version>${org.springframework-version}</version>
        </dependency>

        <dependency>
            <groupid>org.springframework.security</groupid>
            <artifactid>spring-security-config</artifactid>
            <version>${org.springframework-version}</version>
        </dependency>
        
        <!-- AspectJ -->
        <dependency>
            <groupid>org.aspectj</groupid>
            <artifactid>aspectjrt</artifactid>
            <version>${org.aspectj-version}</version>
        </dependency>
       
        
        <!-- Logging -->
        <dependency>
            <groupid>org.slf4j</groupid>
            <artifactid>slf4j-api</artifactid>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupid>org.slf4j</groupid>
            <artifactid>jcl-over-slf4j</artifactid>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupid>org.slf4j</groupid>
            <artifactid>slf4j-log4j12</artifactid>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupid>log4j</groupid>
            <artifactid>log4j</artifactid>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupid>javax.mail</groupid>
                    <artifactid>mail</artifactid>
                </exclusion>
                <exclusion>
                    <groupid>javax.jms</groupid>
                    <artifactid>jms</artifactid>
                </exclusion>
                <exclusion>
                    <groupid>com.sun.jdmk</groupid>
                    <artifactid>jmxtools</artifactid>
                </exclusion>
                <exclusion>
                    <groupid>com.sun.jmx</groupid>
                    <artifactid>jmxri</artifactid>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>

        <!-- @Inject -->
        <dependency>
            <groupid>javax.inject</groupid>
            <artifactid>javax.inject</artifactid>
            <version>1</version>
        </dependency>
          
        <!-- Servlet -->
        <dependency>
            <groupid>javax.servlet</groupid>
            <artifactid>servlet-api</artifactid>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupid>javax.servlet.jsp</groupid>
            <artifactid>jsp-api</artifactid>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupid>javax.servlet</groupid>
            <artifactid>jstl</artifactid>
            <version>1.2</version>
        </dependency>
       
        <!-- Test -->
        <dependency>
            <groupid>junit</groupid>
            <artifactid>junit</artifactid>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
       
    </dependencies>
   <build>
      <plugins>
         <plugin>
            <artifactid>maven-eclipse-plugin</artifactid>
            <version>2.9</version>
            <configuration>
               <additionalProjectnatures>
                  <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
               </additionalProjectnatures>
               <additionalBuildcommands>
                  <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
               </additionalBuildcommands>
               <downloadSources>true</downloadSources>
               <downloadJavadocs>true</downloadJavadocs>
            </configuration>
         </plugin>
         <plugin>
            <groupid>org.apache.maven.plugins</groupid>
            <artifactid>maven-compiler-plugin</artifactid>
            <version>2.3.2</version>
            <configuration>
               <source>1.6</source>
               <target>1.6</target>
               <compilerArgument>-Xlint:all</compilerArgument>
               <showWarnings>true</showWarnings>
               <showDeprecation>true</showDeprecation>
            </configuration>
         </plugin>
         <plugin>
            <groupid>org.codehaus.mojo</groupid>
            <artifactid>exec-maven-plugin</artifactid>
            <version>1.2.1</version>
            <configuration>
               <mainClass>org.test.int1.Main</mainClass>
            </configuration>
         </plugin>
      </plugins>
   </build>
</project>

Затем, выделим настройки безопасности в отдельный файл application-security.xml, изменив в web.xml следующие строки:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/root-context.xml
        /WEB-INF/spring/application-security.xml
    </param-value>
</context-param>

Также необходимо добавить фильтры Spring Security в файле 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>

web.xml

<?xml version ="1.0" encoding ="UTF-8"?>
<web-app version ="2.5" xmlns ="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemalocation ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- The definition of the Root Spring Container shared by all Servlets 
    and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/root-context.xml
            /WEB-INF/spring/application-security.xml
        </param-value>
    </context-param>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <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>

</web-app>

Собственно настройки Spring Security (файл application-security.xml) выглядят следующим образом:


<?xml version ="1.0" encoding ="UTF-8"?>
<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.1.xsd">

 <http pattern ="/css/**" security ="none" />
 
 <http auto-config ="true">
     <intercept-url pattern ="/secure/**" access ="ROLE_USER" />
     <intercept-url pattern ="/admin/**" access ="ROLE_ADMIN" />
 </http>
 

 <authentication-manager>
     <authentication-provider>
         <user-service>
             <user name ="admin" password ="adminpassword" authorities ="ROLE_USER, ROLE_ADMIN" />
             <user name ="user" password ="userpassword" authorities ="ROLE_USER" />
         </user-service>
     </authentication-provider>
 </authentication-manager>
</beans:beans>
 

Это максимально упрощенный пример. Рассмотрим каждую часть данной конфигурации.

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name ="admin" password ="adminpassword" authorities ="ROLE_USER, ROLE_ADMIN" />
            <user name ="user" password ="userpassword" authorities ="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>

С помощью кода, который представлен выше, создается два пользователя в памяти: user с паролем userpassword и admin с паролем adminpassword. Также есть другие способы получения пользователей: из базы данных, из LDAP и др. Они будут рассмотрены в следующих частях статьи.

Обратите внимание, что пользователю user cразу же предоставляется роль ROLE_USER, а пользователю admin - две роли ROLE_USER и ROLE_ADMIN. В конечном итоге пользователю admin будут доступны все страницы из примера, а пользователю user - только некоторые.

<http auto-config ="true">
    <intercept-url pattern ="/secure/**" access ="ROLE_USER" />
    <intercept-url pattern ="/admin/**" access ="ROLE_ADMIN" />
</http>

Если анонимный пользователь попытается зайти на страницу /secure/, он будет перенаправлен на страницу авторизации.

Рис 1. Страница авторизации
Рис 1. Страница авторизации

Этой страницы нет в проекте, она создается Spring Security автоматически благодаря атрибуту auto-config="true" тега http. Как привести ее в нужный пользователю вид будет рассказано в следующих главах.

Если пользователь user попытается зайти на страницу с адресом /admin/, он увидит следующую страницу:

Рис 2. HTTP Status 403 - Access is denied
Рис 2. HTTP Status 403 - Access is denied

О том, как привести страницу с HTTP-ошибкой в привлекательный вид рассказано в статье Ошибки HTTP-протокола в Spring MVC.

Последняя нерассмотренная строка конфигурации сообщает Spring Security, что все ресурсы, которые начинаются с адреса /css/ являются публичными:

<http pattern ="/css/**" security ="none" />

Скачать проект, демонстрирующий работу примера из статьи, Вы можете по следующей ссылке - Скачать spring-security-basics.zip.

30.08.2015

    Только зарегистрированные пользователи могут оставить комментарий.
    Вернуться в список
    2017 «Инфокристалл» Сборка от 18.04.2017 03:58
    Контакты | Задать вопрос

    Карта сайта