Пару недель назад я написал учебник о том, как реализовать безопасность с помощью Spring Security . За неделю до этого я написал аналогичное руководство для Java EE 6 . На этой неделе я хотел бы показать вам, как реализовать те же функции с помощью Apache Shiro . Как я упоминал в предыдущих статьях, я пишу это, потому что я сказал аудитории в апреле UJUG, что я буду публиковать скриншоты демонстраций.
Сегодня я закончил третий скринкаст, показывающий, как реализовать безопасность с помощью Apache Shiro. Ниже представлена презентация (с включенной на слайде 22 скринкастом), а также пошаговое руководство.
Apache Shiro Войти Учебник
- Загрузите и запустите приложение
- Реализовать базовую аутентификацию
- Принудительно SSL
- Реализовать аутентификацию на основе форм
- Хранить пользователей в базе данных
- Резюме
Загрузите и запустите приложение.
Для начала загрузите приложение, в котором вы будете внедрять систему безопасности. Это приложение является урезанной версией приложения Ajax Login, которое я написал для своей статьи о реализации Ajax-аутентификации с использованием jQuery, Spring Security и HTTPS . Для запуска приложения вам потребуется Java 6 и Maven. Запустите его, используя mvn jetty: run и откройте http: // localhost: 8080 в вашем браузере. Вы увидите, что это простое приложение CRUD для пользователей, и для добавления или удаления пользователей не требуется вход в систему.
Реализация базовой аутентификации
Первым шагом является защита экрана списка, чтобы людям приходилось входить в систему для просмотра пользователей. Для этого вам нужно создать файл Shiro.ini для конфигурации Shiro. Создайте src / main / resources / shiro.ini и заполните его содержимым ниже:
[main] [users] admin = admin, ROLE_ADMIN [roles] ROLE_ADMIN = * [urls] /app/users = authcBasic
Вы можете видеть, что этот файл имеет четыре раздела и довольно прост для чтения и понимания. Для получения дополнительной информации о том, для чего предназначен каждый раздел, ознакомьтесь с документацией по конфигурации Shiro .
Затем откройте src / main / webapp / WEB-INF / web.xml и добавьте IniShiroFilter Широ:
<filter>
<filter-name>securityFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
<!-- no init-param means load the INI config from classpath:shiro.ini -->
</filter>
И добавьте его сопоставление фильтра сразу после rewriteFilter в разделе сопоставления фильтра (порядок важен!):
<filter-mapping>
<filter-name>rewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
Затем добавьте основные и веб- зависимости Широ в ваш pom.xml:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.1.0</version>
</dependency>
На этом этапе, если вы перезапустите Jetty (Ctrl + C и Jetty: запустите снова), вам будет предложено войти в систему, когда вы нажмете на вкладку «Пользователи». Введите admin / admin для входа. Apache Shiro проще в настройке, чем Spring Security, в основном потому, что для него не требуется XML.
После входа в систему вы можете попытаться выйти, нажав ссылку «Выйти» в правом верхнем углу. Это вызывает LogoutController со следующим кодом, который выводит пользователя из системы.
public void logout(HttpServletResponse response) throws ServletException, IOException {
request.getSession().invalidate();
response.sendRedirect(request.getContextPath());
}
ПРИМЕЧАНИЕ. В настоящее время у Shiro нет способа выхода из системы с помощью API. Тем не менее, он будет добавлен в версии 1.2 .
Вы заметите, что щелкнув по этой ссылке, вы не выйдете из системы, даже если сеанс признан недействительным. Единственный способ выйти из системы с базовой аутентификацией — закрыть браузер. Чтобы получить возможность выхода из системы, а также получить больший контроль над внешним видом входа в систему, вы можете реализовать аутентификацию на основе форм. Перед тем, как вы внедрите аутентификацию на основе форм, я хотел бы показать вам, как легко использовать SSL с Apache Shiro.
Принудительное использование SSL
Apache Shiro позволяет принудительно использовать SSL для URL-адреса, просто добавив «ssl [ порт ]» к URL-адресу в разделе [urls]. Если вы не укажете порт, он будет использовать порт по умолчанию (443). Я не уверен, позволяет ли он вам переключиться обратно на http, как требует канал безопасности Spring Spring , но я не думаю, что это так. Измените раздел URL вашего shiro.ini, чтобы иметь следующее:
[urls] /app/users = ssl[8443],authc
Чтобы это работало, вы должны настроить Jetty на прослушивание порта SSL. Добавьте следующее сразу после элемента </ webAppConfig> для jetty-maven-plugin в вашем файле pom.xml:
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<forwarded>true</forwarded>
<port>8080</port>
</connector>
<connector implementation="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
<forwarded>true</forwarded>
<port>8443</port>
<maxIdleTime>60000</maxIdleTime>
<keystore>${project.build.directory}/ssl.keystore</keystore>
<password>appfuse</password>
<keyPassword>appfuse</keyPassword>
</connector>
</connectors>
Хранилище ключей должно быть сгенерировано для успешного запуска Jetty, поэтому добавьте keytool-maven-plugin чуть выше jetty-maven-plugin в pom.xml.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>keytool-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>generate-resources</phase>
<id>clean</id>
<goals>
<goal>clean</goal>
</goals>
</execution>
<execution>
<phase>generate-resources</phase>
<id>genkey</id>
<goals>
<goal>genkey</goal>
</goals>
</execution>
</executions>
<configuration>
<keystore>${project.build.directory}/ssl.keystore</keystore>
<dname>cn=localhost</dname>
<keypass>appfuse</keypass>
<storepass>appfuse</storepass>
<alias>appfuse</alias>
<keyalg>RSA</keyalg>
</configuration>
</plugin>
Теперь, если вы перезапустите Jetty, перейдите по адресу http: // localhost: 8080 и перейдите на вкладку «Пользователи», вам будет предложено принять ненадежный сертификат, а затем после входа будет перенаправлен на https: // localhost: 8443 / users ,
Теперь давайте рассмотрим, как лучше контролировать внешний вид экрана входа в систему, а также как заставить выход из системы работать с аутентификацией на основе форм.
Реализация аутентификации на основе форм
Чтобы перейти от базовой аутентификации на основе форм, вам просто нужно добавить несколько строк в shiro.ini. Прежде всего, поскольку я бы не хотел менять имя элементов ввода в login.jsp, переопределите имена по умолчанию в разделе [main]:
# name of request parameter with username; if not present filter assumes 'username' authc.usernameParam = j_username # name of request parameter with password; if not present filter assumes 'password' authc.passwordParam = j_password authc.failureKeyAttribute = shiroLoginFailure
Затем измените раздел [urls] для фильтрации на login.jsp и используйте «authc» вместо «authcBasic»:
[urls] # The /login.jsp is not restricted to authenticated users (otherwise no one could log in!), but # the 'authc' filter must still be specified for it so it can process that url's # login submissions. It is 'smart' enough to allow those requests through as specified by the # shiro.loginUrl above. /login.jsp = authc /app/users = ssl[8443],authc
Затем измените login.jsp так, чтобы действие формы было пустым (что приводило к его отправке на себя) вместо j_security_check:
1.
<
form
action
=
""
id
=
"loginForm"
method
=
"post"
>
Теперь перезапустите Jetty, и вам будет предложено войти в систему с помощью этого JSP вместо обычного диалога аутентификации.
Хранение пользователей в базе данных
Чтобы хранить пользователей в базе данных, а не в файле, вам нужно добавить несколько параметров в shiro.ini, чтобы определить базу данных и таблицы для использования. Откройте src / main / resources / shiro.ini и добавьте следующие строки в раздел [main].
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm #jdbcRealm.permissionsLookupEnabled=false # If not filled, subclasses of JdbcRealm assume "select password from users where username = ?" jdbcRealm.authenticationQuery = select user_pass from users where user_name = ? # If not filled, subclasses of JdbcRealm assume "select role_name from user_roles where username = ?" jdbcRealm.userRolesQuery = select role_name from users_roles where user_name = ? ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource ds.serverName = localhost ds.user = root ds.databaseName = appfuse jdbcRealm.dataSource = $ds
Эта конфигурация аналогична той, что я делал в учебном руководстве по Java EE 6, где я указываю на базу данных, отличную от экземпляра H2, который используется приложением. Я полагаю, что Широ может общаться с DAO, как Spring Security, но мне еще предстоит изучить этот вариант.
Пока вы это делаете, добавьте следующие строки, чтобы включить шифрование пароля.
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher jdbcRealm.credentialsMatcher = $sha256Matcher
Вам нужно будет установить MySQL, чтобы это работало. После его установки вы сможете создать базу данных appfuse с помощью следующей команды:
mysql -u root -p -e 'create database appfuse'
Затем создайте необходимые таблицы и заполните их пользователем «admin». Войдите в систему с помощью «mysql -u root -p appfuse» и выполните следующие операторы SQL:
create table users ( user_name varchar(30) not null primary key, user_pass varchar(100) not null ); create table user_roles ( user_name varchar(30) not null, role_name varchar(30) not null, primary key (user_name, role_name) ); insert into users values ('admin', '22f256eca1f336a97eef2b260773cb0d81d900c208ff26e94410d292d605fed8'); insert into user_roles values ('admin', 'ROLE_ADMIN');
Теперь, если вы перезапустите Jetty, вы сможете войти с помощью admin / adminjdbc и просмотреть список пользователей.
Резюме
В этом руководстве вы узнали, как реализовать аутентификацию с использованием Apache Shiro 1.1.0. У меня нет большого опыта работы с Apache Shiro, но я смог заставить работать основы без особых усилий. Этот урок не показывает, как сделать «Помни меня», потому что я не смог понять это за 5 минут, а это значит, что у меня есть еще 5 минут, прежде чем он провалит 10-минутный тест.
Широ ранее назывался JSecurity и был проектом Apache менее года. Похоже, что он в большей степени ориентирован на не-веб-использование, поэтому на него, безусловно, стоит обратить внимание, если вы больше заинтересованы в криптографии или не-веб-приложениях. Я думаю, что есть хороший шанс, что этот проект будет продолжать расти и использоваться больше, поскольку все больше разработчиков узнают об этом. Бренд Apache определенно не повредит.
Я не включил слайд об ограничениях, которые я нашел с Широ, главным образом потому, что я не использовал это много. Я использовал Java EE и Spring Security в течение нескольких лет. Основным ограничением, которое я обнаружил, было отсутствие документации, но я слышал, что она быстро улучшается.
Это знаменует конец этой серии по реализации безопасности в веб-приложениях Java. Я представлю эту тему в Jazoon, а также полную версию (со взломом) на ÜberConf . Надеюсь, увидимся на одной из этих конференций.
От http://raibledesigns.com/rd/entry/java_web_application_security_part2