2016-11-22 5 views
0

Ich entwickle ein Spring MVC Projekt und möchte meinen eigenen Authentifizierungsinterceptor implementieren. Es sieht wie folgt aus:Wie bekomme ich den aktuellen Benutzer in Interceptors und erhalte seine Ressourcen in den Controllern

@Component 
public class AuthenticationInterceptor extends HandlerInterceptorAdapter { 

    @Autowired 
    private UsersRepo usersRepo; 

    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
     if (!(handler instanceof HandlerMethod)) return true; 
     HandlerMethod handlerMethod = (HandlerMethod) handler; 

     if (handlerMethod.getMethodAnnotation(Authenticated.class) == null) return true; 

     HttpSession session = request.getSession(false); 
     if (session == null) return reject(response); 

     Long id = (Long) session.getAttribute("userId"); 
     if (id == null) return reject(response); 

     User user = usersRepo.findOne(id); 
     if (user == null) return reject(response); 

     RequestContext.CURRENT_USER.set(user); 

     return true; 
    } 

    @Override 
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
     RequestContext.CURRENT_USER.remove(); 
    } 

    private boolean reject(HttpServletResponse response) { 
     response.setStatus(403); 
     return false; 
    } 
} 

RequestContext.CURRENT_USER ein ThreadLocal<User> ist.

In der Steuerung möchte ich den Befehl des aktuellen Benutzers abzurufen:

mich
@RestController 
@RequestMapping("/orders") 
public class OrdersController { 

    @RequestMapping(method = RequestMethod.GET) 
    @Authenticated 
    public Collection<Order> index() { 
     Collection<Order> orders = RequestContext.CURRENT_USER.get().getOrders(); 
     return orders; 
    } 

} 

Es gibt Could not write content: failed to lazily initialize a collection of role: myapp.models.User.orders, could not initialize proxy - no Session.

Ich denke, das ist, weil Hibernate die Datenbanksitzung geschlossen hat, wenn es die Arbeit erledigt ist die aktuellen User in dem Abfangjäger zu finden, und es ist somit nicht in der Lage zu nutzen, dass UserOrder s in einer anderen Sitzung zu laden. Aber ich möchte wirklich nicht wieder auf die Datenbank zugreifen. Wie kann ich den aktuellen Benutzer in den Interceptor laden und diese Benutzerinstanz wiederverwenden, um mehr Ressourcen zu laden?

+0

_ frisch Benutzer abrufen „Aber ich wieder wirklich nicht wollen, Datenbank schlagen.“ _ _ "Wie kann ich aktuelle Benutzer in Interceptor laden und diese Benutzerinstanz wieder verwenden mehr zu laden Ressourcen "_ Das ist ein ziemlicher Widerspruch. – zeroflagL

Antwort

0

Sie müssen die Auftragssammlung initialisieren, bevor Sie den Benutzer im lokalen Thread speichern. Rufen Sie

user.getOrders(); 

vor

RequestContext.CURRENT_USER.set(user); 

, oder Sie Benutzer-ID speichern. Wenn Sie benötigen Aufträge von aktuellen Benutzer

public Collection<Order> index() { 
    User user = usersRepo.findOne(RequestContext.CURRENT_USER.get()); 
    Collection<Order> orders = user.getOrders(); 
    return orders; 
} 
+0

Nein, ich möchte keine Bestellungen für jede Anfrage laden. – Aetherus

+0

Lesen Sie den Benutzer dann erneut. Verwenden Sie Repo, um den gleichen Benutzer nach ID zu finden (Sie können die ID des gespeicherten Benutzers verwenden) und erhalten Bestellungen von dem neu abgerufenen Benutzer – StanislavL

+0

Danke für den Vorschlag. Ich versuche diesen Ansatz, obwohl ich nicht die Idee mag, Datenbank zweimal mit genau identischen Abfragen zu treffen. – Aetherus

Verwandte Themen