Apache Shiro для защиты REST API

Я пытаюсь интегрировать Широ в свое весеннее приложение mvc. Аутентификация поддерживается сервером LDAP, и я могу успешно пройти аутентификацию на сервере ldap и получить файл cookie.

Чего я не могу сделать, так это использовать этот файл cookie в последующих запросах и получить результаты. Попытка использовать файл cookie дает мне HTTP 302 для повторной аутентификации. Например: GET on ( rest/assets/list ) с заголовком Cookie: JSESSIONID=abcd перенаправляет на (rest/login)

Это правильная стратегия для защиты API? API используется приложением AngularJS, и я хотел бы включить аутентификацию на основе группы пользователей, прежде чем добавлять возможность CRUD.

Любые указатели будут полезны.

Исходный код следующим образом:

Файл applicationContext.xml выглядит следующим образом

 <beans xmlns="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.xsd">


<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"/>

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>

<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager"/>
</bean>

<bean id="ldapRealm" class="com.directv.nmsupport.security.LDAPRealm">
    <property name="contextFactory" ref="ldapContextFactory" />
    <property name="userDnTemplate" value="uid={0},ou=DirecTV,ou=People,dc=swengdtv,dc=net" />
</bean>

<bean id="ldapContextFactory" class="org.apache.shiro.realm.ldap.JndiLdapContextFactory">
    <property name="url" value="ldap://teon:389"/>
</bean>

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="ldapRealm"/>
    <property name="cacheManager" ref="cacheManager"/>
    <property name="sessionManager" ref="sessionManager" />
</bean>

<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <property name="sessionIdCookieEnabled" value="true" />
</bean>

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/rest/login"/>
    <property name="filterChainDefinitions">
        <value>
            /rest/login = anon
            /rest/** = user
        </value>
    </property>
</bean>
</beans>

Код LDAPRealm.java

public class LDAPRealm extends JndiLdapRealm {

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    String username = (String) getAvailablePrincipal(principals);
    return super.doGetAuthorizationInfo(principals);    //To change body of overridden methods use File | Settings | File Templates.
}

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    return super.doGetAuthenticationInfo(token);    //To change body of overridden methods use File | Settings | File Templates.
}

}

Логинконтроллер.java

@Controller
public class LoginController {

@RequestMapping(value = "/login", method = RequestMethod.POST)
public void login(@RequestBody UserCredentials user) {
    UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
    token.setRememberMe(true);
    SecurityUtils.getSecurityManager().authenticate(token);
    Subject subject = SecurityUtils.getSubject();
    subject.getSession(true);
}

@RequestMapping(value="/logout")
public void logout() {
    Subject subject = SecurityUtils.getSubject();
    SecurityUtils.getSecurityManager().logout(subject);
}

}

Ведение журнала от apache shiro

17:47:54.428 ["http-bio-8080"-exec-7] DEBUG o.a.shiro.realm.ldap.JndiLdapRealm - Authenticating user 'afulara' through LDAP
17:47:54.428 ["http-bio-8080"-exec-7] DEBUG o.a.s.r.ldap.JndiLdapContextFactory - Initializing LDAP context using URL [ldap://teon:389] and principal [uid=afulara,ou=DirecTV,ou=People,dc=swengdtv,dc=net] with pooling disabled
17:47:54.431 ["http-bio-8080"-exec-7] DEBUG o.a.shiro.realm.AuthenticatingRealm - Looked up AuthenticationInfo [afulara] from doGetAuthenticationInfo
17:47:54.431 ["http-bio-8080"-exec-7] DEBUG o.a.shiro.realm.AuthenticatingRealm - AuthenticationInfo caching is disabled for info [afulara].  Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - afulara, rememberMe=true].
17:47:54.431 ["http-bio-8080"-exec-7] DEBUG o.a.s.authc.AbstractAuthenticator - Authentication successful for token [org.apache.shiro.authc.UsernamePasswordToken - afulara, rememberMe=true].  Returned account [afulara]
17:48:20.927 ["http-bio-8080"-exec-9] DEBUG o.a.shiro.web.servlet.SimpleCookie - Found 'JSESSIONID' cookie value [02b41ee8-e9e3-43e5-8ee3-aae72322fede]
17:48:24.204 ["http-bio-8080"-exec-10] DEBUG o.a.shiro.web.servlet.SimpleCookie - Found 'JSESSIONID' cookie value [02b41ee8-e9e3-43e5-8ee3-aae72322fede]
17:48:24.210 ["http-bio-8080"-exec-10] WARN  o.s.web.servlet.PageNotFound - Request method 'GET' not supported

person Adil F    schedule 29.05.2013    source источник
comment
Следовать за. У меня никогда не получалось, чтобы это работало, и я переключился на Spring Security и обнаружил, что он более поддерживается (сообществом и поиском в Google), и завершил это действие.   -  person Adil F    schedule 31.05.2013
comment
Затем используйте функцию «Ответить на свой вопрос». Таким образом, люди могут быстро узнать, что ваша проблема уже решена.   -  person dnang    schedule 02.11.2013
comment
Я думаю, что это не правильная стратегия. Согласно принципам REST, вы не должны создавать сеанс с клиентом. Лучшими способами защиты REST API являются базовая аутентификация и OAuth.   -  person vincenzo iafelice    schedule 22.11.2013


Ответы (2)


Идея REST заключается в том, что он не имеет состояния, поэтому, если вы создадите сеанс с клиентом, вы нарушите принципы RESTful API. Я бы рекомендовал использовать Spring Security, здесь вы можете найти простой пример: http://spring.io/guides/gs/securing-web/. Это займет у вас около 5-10 минут, после чего вы сможете использовать его в своем проекте.

Также есть простое руководство по подключению к системе LDAP: http://spring.io/guides/gs/authenticating-ldap/

ОБНОВЛЕНИЕ: Увидев ваш комментарий к вашему вопросу, я бы посоветовал вам ответить на ваш вопрос с результатом, который вы получили.

person DominikAngerer    schedule 24.01.2015

Поскольку люди просили, чтобы я опубликовал свой ответ как отдельный ответ, вот он.

Я не использовал Apache Shiro.

PS: Не то, чтобы Apache shiro плохой. Я просто обнаружил, что Spring Security проще использовать для моих конкретных нужд. YMMV

person Adil F    schedule 26.01.2015