2015-06-02 3 views
1

Я использую Guice + Jersey + Shiro для входа в систему через REST API, а затем использую тот же HTTP-сеанс, под которым я вошел, и мои разрешения работают для этого ресурса.Тема не завершена в сеансе после входа в систему с Shiro

Ниже приведен мой код.

Во-первых, моя конфигурация сервлета: -

public class ServletConfiguration extends GuiceServletContextListener 
{ 
    private ServletContext mServletContext; 

    @Override 
    public void contextInitialized(ServletContextEvent inEvent) 
    { 
     mServletContext = inEvent.getServletContext(); 

     super.contextInitialized(inEvent); 
    } 

    @Override 
    protected Injector getInjector() 
    { 
     mServletContext.addListener(new au.com.tt.agora.configuration.CbiCleanupHttpSessionListener()); 

     return Guice.createInjector(new JerseyServletModule() { 
      @Override 
      protected void configureServlets() 
      { 
       install(new TTShiroWebModule(mServletContext)); 
       install(new ShiroAopModule()); 

       filter("/*").through(GuiceShiroFilter.class); 

       bind(ShiroLoginResource.class); 
       bind(ShiroResource.class); 

       filter("/*").through(GuiceContainer.class); 
      } 
     }); 
    } 
} 

Теперь это мой тест царством: -

пакет au.com.tt.agora.configuration.shiro;

import org.apache.shiro.authc.AuthenticationException; 
import org.apache.shiro.authc.AuthenticationInfo; 
import org.apache.shiro.authc.AuthenticationToken; 
import org.apache.shiro.authc.SimpleAuthenticationInfo; 
import org.apache.shiro.authc.UsernamePasswordToken; 
import org.apache.shiro.authz.AuthorizationInfo; 
import org.apache.shiro.authz.SimpleAuthorizationInfo; 
import org.apache.shiro.realm.AuthorizingRealm; 
import org.apache.shiro.subject.PrincipalCollection; 

public class TestRealm extends AuthorizingRealm 
{ 

    @Override 
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken inToken) throws AuthenticationException 
    { 
     UsernamePasswordToken upToken = (UsernamePasswordToken) inToken; 

     if (upToken.getUsername().equals("Kamal") || upToken.getUsername().equals("NotKamal")) 
      return new SimpleAuthenticationInfo(upToken.getUsername(), upToken.getPassword(), getName()); 

     return null; 
    } 

    @Override 
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection inPrincipals) 
    { 
     String username = (String) inPrincipals.fromRealm(getName()).iterator().next(); 
     SimpleAuthorizationInfo authzInfo = new SimpleAuthorizationInfo(); 
     if (username.equals("Kamal")) 
     { 
      authzInfo.addStringPermission("PRODMA:READ:AU"); 
      authzInfo.addStringPermission("PRODMA:WRITE:KB"); 
      authzInfo.addStringPermission("SUPPMA:READ:KB"); 
     } 
     else 
     { 
      authzInfo.addStringPermission("PRODMA:READ:AU"); 
      authzInfo.addStringPermission("PRODMA:WRITE:KB"); 
     } 

     return authzInfo; 
    } 
} 

Это веб-модуль

package au.com.tt.agora.configuration.shiro; 

import javax.servlet.ServletContext; 

import org.apache.shiro.guice.web.ShiroWebModule; 

public class TTShiroWebModule extends ShiroWebModule 
{ 

    public TTShiroWebModule(ServletContext inServletContext) 
    { 
     super(inServletContext); 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    protected void configureShiroWeb() 
    { 
     bindRealm().to(TestRealm.class); 
     addFilterChain("**/shiroResource/*", ANON); 
    } 

} 

Вот ресурс я использую для входа: -

package au.com.tt.agora.configuration.jaxrs.resources; 

import javax.servlet.http.HttpServletRequest; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType; 

import org.apache.commons.httpclient.UsernamePasswordCredentials; 
import org.apache.shiro.SecurityUtils; 
import org.apache.shiro.authc.AuthenticationToken; 
import org.apache.shiro.authc.UsernamePasswordToken; 
import org.apache.shiro.subject.Subject; 

import com.google.inject.Inject; 

import au.com.tt.agora.configuration.option.ClientProvider; 
import au.com.tt.agora.configuration.option.ConfigurationProvider; 
import au.com.tt.agora.login.web.request.LoginRequest; 
import au.com.tt.agora.login.web.request.LoginResponse; 
import au.com.tt.agora.login.web.service.LoginHandler; 
import au.com.tt.calypso.cbi.CalypsoException; 

@Path("/{client}/shiroLogin") 
public class ShiroLoginResource 
{ 
    private static final String ROUTING_TOKEN_HEADER = "proxy-jroute"; 

    @POST 
    @Path("/standard") 
    @Produces(MediaType.TEXT_PLAIN) 
    @Consumes(MediaType.APPLICATION_JSON) 
    public String login(@Context HttpServletRequest inServletRequest) throws CalypsoException 
    { 
     Subject subject = SecurityUtils.getSubject(); 
     subject.login(new UsernamePasswordToken("Kamal", "Password", false)); 
     return getSessionIdWithRouting(inServletRequest); 
    } 

    private String getSessionIdWithRouting(HttpServletRequest inRequest) 
    { 
     String sessionId = inRequest.getSession().getId(); 

     return(sessionId); 
    } 
} 

А вот ресурс я звоню: -

package au.com.tt.agora.configuration.jaxrs.resources; 

import javax.servlet.http.HttpSession; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 

import org.apache.shiro.SecurityUtils; 
import org.apache.shiro.authz.annotation.RequiresPermissions; 
import org.apache.shiro.subject.Subject; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import com.google.inject.Inject; 

@Path("/{client}/shiroResource") 
public class ShiroResource 
{ 
    private static final Logger LOG = LoggerFactory.getLogger(ShiroResource.class); 

    @Inject 
    public ShiroResource() 
    { 
    } 

    @POST 
    @Path("requiresProdma.do") 
    @Produces(MediaType.TEXT_PLAIN) 
    @RequiresPermissions({ "PRODMA:*:*" }) 
    public String prodmaRequired() 
    { 
     return "Success"; 
    } 

    @POST 
    @Path("requiresSuppma.do") 
    @Produces(MediaType.TEXT_PLAIN) 
    @RequiresPermissions({ "SUPPMA:*:*" }) 
    public String suppmaRequired() 
    { 
     Subject subject = SecurityUtils.getSubject(); 
     subject.getPrincipal(); 
     return "Success"; 
    } 
} 

Если я поставил точку останова в suppmaRequired и назовите этот ресурс, я вижу, что объект не аутентифицирован.

Мое понимание о том, как работает Сиро, очевидно, ошибочно, но я не знаю, чего я не делаю. Может кто-то указать мне верное направление?

Не уверен, что это имеет значение, но я использую URL-переписывание для доступа к веб-сессии.

В принципе, я использую API-интерфейс для проверки этого. Вот пример: -

fetch("http://localhost/app/tt/shiroLogin/standard", { 
    method: "POST", 
    headers: { 
    "Content-Type" : "application/json" 
    } , 
    body: '{"username":"myName","password":"myPassword"}' 
}) 
.then(function(res) { 
    return res.text(); 
}) 
.then(function(sessionId) { 
    return fetch("http://localhost/app/tt/shiroResource/requiresSuppma.do;JSESSIONID=" + sessionId, 
       { 
       method: "POST" 
       }); 
}) 
.then(function(res) { 
    return res.text(); 
}) 
.then(function(res) { 
    console.log(res); 
}); 

Я также размещаю на стеклянной рыбке.

ответ

0

ОК, в конце концов это не проблема с Широ. Я использовал две разные сессии, идущие от ShiroLoginResource до ShiroResource.

Я забыл, что вам действительно нужно было ввести объект уровня сеанса в Guice, чтобы заставить Guice создать сеанс. Глупый я.

Как только я ввел зависимую от сеанса связь в ShiroLoginResource и взаимодействовал с ней, тогда все просто сработало.

Я буду держать этот вопрос открытым, потому что он дает некоторые полезные фрагменты кода.