Статьи

Добавление Http Basic Auth к сервисам RESTful в Java и Spring

Добавить базовую HTTP-аутентификацию в набор сервисов на основе Spring MVC очень просто. Из этого туториала вы узнаете, как быстро настроить аутентификацию, сохраняя набор имен пользователей, паролей и ролей в файле конфигурации Spring и связывая с ними шаблоны URL-адресов для платформы, чтобы определить, авторизован пользователь или нет. Для более надежной аутентификации и авторизации, когда вы можете использовать сервер каталогов и LDAP, требуются дополнительные конфигурации, которые не обсуждаются в этом посте.

В этом уроке я буду работать с предположением, что у вас уже есть работающее приложение, созданное с помощью Spring MVC. Если вы это сделаете, на самом деле есть только два шага. Давайте начнем:

1. Добавление зависимостей

Первое, что вам нужно сделать, это получить соответствующие пружинные модули безопасности. Добавьте эти зависимости в ваш pom.xml

<dependency>
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-web</artifactId>
       <version>${org.springframework.version}</version>
       <type>jar</type>
       <scope>compile</scope>
</dependency>
<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${org.springframework.version}</version>
        <type>jar</type>
        <scope>compile</scope>
</dependency>

2. Изменение файла web.xml

Первое, что мы делаем, это добавляем фильтр DelegatingFilterProxy . Это стандартный фильтр сервлета, который делегирует ответственность бобу Spring. Другими словами, вы можете обеспечить поддержку Spring для фильтров сервлетов через DelegatingFilterProxy . В нашем примере мы будем использовать DelegatingFilterProxy для делегирования полномочий по аутентификации (и, в конечном итоге, авторизации) пружинному компоненту. Добавьте следующий XML в ваш 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>

<listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:security-context.xml</param-value>
</context-param>

3. Создание контекста безопасности xml и размещение его в пути к классам

В строке 16 приведенного выше фрагмента файла web.xml я ссылаюсь на файл security-context.xml. Это загружается в весенний контекст при запуске приложения и состоит из наших настроек безопасности. Вот как выглядит этот файл:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/security

           http://www.springframework.org/schema/security/spring-security-3.0.xsd">

<security:http auto-config='true'>
     <security:intercept-url pattern="/logs/**" access="ROLE_USER, ROLE_ADMIN"/>
     <security:intercept-url pattern="/logviewer.html" access="ROLE_USER, ROLE_ADMIN"/>
     <security:intercept-url pattern="/qr/**" access="ROLE_USER, ROLE_ADMIN"/>
     <!-- security:intercept-url pattern="/sms/**" access="ROLE_USER, ROLE_ADMIN"/-->
     <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
     <security:http-basic />
</security:http>

<security:authentication-manager>
     <security:authentication-provider>
         <security:user-service>
              <security:user name="username1" password="password1" authorities="ROLE_USER" />
              <security:user name="username2" password="password2" authorities="ROLE_USER, ROLE_ADMIN" />
              </security:user-service>
     </security:authentication-provider>
</security:authentication-manager>
</beans>

Не забудьте добавить пространство имен и объявления xsd для безопасности (строки 4 и 9). В строках с 13 по 17 мы предоставляем сопоставления URL-адресов с ролями. Параметры ROLE_ — это роли в приложении, где это могут быть роли, определенные в базе данных или группах в активном каталоге и т. Д. IS_AUTHENTICATED_ANONYMOUSLY используется для указания того, что вы можете войти анонимно. Таким образом, приведенные выше настройки позволяют анонимно обслуживать все запросы без аутентификации, за исключением 3-х, которые требуют аутентификации. Перехваты оцениваются сверху вниз, что означает, что если бы <security: intercept-url pattern = ”/ **” access = ”IS_AUTHENTICATED_ANONYMOUSLY” /> был первым в списке, все запросы проходили бы.

4. Вызов службы

Давайте посмотрим, что происходит, когда мы вызываем URL-адрес, настроенный для аутентификации. Мы получаем всплывающее окно с запросом имени пользователя и пароля.

Если вы введете неверное имя пользователя и / или пароль, вы получите ошибку HTTP 415

 Давайте посмотрим на заголовок HTTP-запроса при успешном входе

 На изображении выше вы заметите, что есть атрибут заголовка Authorization. Если мы декодируем его с помощью любого декодера Base64, мы получаем username1: password1. Вы можете видеть, что базовая аутентификация HTTP просто берет ваше имя пользователя и пароль, объединяет их как имя пользователя: пароль, а затем кодирует их в Base64 и отправляет по сети. with value Basic dXNlcm5hbWUxOnBhc3N3b3JkMQ==

Суть в том, что базовая аутентификация HTTP очень проста в реализации и лучше, чем вообще отсутствие защиты, но уязвима и должна быть заменена более надежным механизмом, таким как Digest Authentication, который я могу обсудить в будущем посте.