001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.messaging.service.security;
022    
023    import java.lang.reflect.InvocationTargetException;
024    import java.security.Principal;
025    import java.util.Map;
026    
027    import javax.servlet.http.HttpServletRequest;
028    import javax.servlet.http.HttpSession;
029    
030    import org.granite.context.GraniteContext;
031    import org.granite.messaging.webapp.HttpGraniteContext;
032    import org.mortbay.jetty.HttpConnection;
033    import org.mortbay.jetty.Request;
034    import org.mortbay.jetty.security.UserRealm;
035    
036    /**
037     * @author William DRAI
038     */
039    public class Jetty6SecurityService extends AbstractSecurityService {
040    
041        private static final String JETTY6_AUTH = "org.granite.messaging.service.security.Jetty6Auth";
042    
043    
044        public Jetty6SecurityService() {
045            super();
046        }
047    
048    
049        public void configure(Map<String, String> params) {
050        }
051    
052    
053        public void login(Object credentials) throws SecurityServiceException {
054            String[] decoded = decodeBase64Credentials(credentials);
055    
056            HttpGraniteContext graniteContext = (HttpGraniteContext)GraniteContext.getCurrentInstance();
057            HttpServletRequest httpRequest = graniteContext.getRequest();
058            Request request = httpRequest instanceof Request ? (Request)httpRequest : HttpConnection.getCurrentConnection().getRequest();
059            UserRealm realm = request.getUserRealm();
060    
061            Principal principal = realm.authenticate(decoded[0], decoded[1], request);
062            if (principal == null) {
063                if (request.getSession(false) != null)
064                    request.getSession(false).removeAttribute(JETTY6_AUTH);
065                throw SecurityServiceException.newInvalidCredentialsException("Wrong username or password");
066            }
067    
068            request.setAuthType(AUTH_TYPE);
069            request.setUserPrincipal(principal);
070    
071            request.getSession().setAttribute(JETTY6_AUTH, principal);
072            
073            endLogin(credentials);
074        }
075    
076    
077        public Object authorize(AbstractSecurityContext context) throws Exception {
078    
079            startAuthorization(context);
080    
081            HttpGraniteContext graniteContext = (HttpGraniteContext)GraniteContext.getCurrentInstance();
082            HttpServletRequest httpRequest = graniteContext.getRequest();
083    
084            boolean reauth = false;
085            Principal principal = httpRequest.getUserPrincipal();
086            if (principal == null) {
087                HttpSession session = httpRequest.getSession(false);
088                principal = session != null ? (Principal)session.getAttribute(JETTY6_AUTH) : null;
089                reauth = true;
090            }
091    
092            if (principal == null && tryRelogin()) {
093                    principal = httpRequest.getUserPrincipal();
094                    reauth = false;
095            }
096            
097            if (principal == null) {
098                if (httpRequest.getRequestedSessionId() != null) {
099                    HttpSession httpSession = httpRequest.getSession(false);
100                    if (httpSession == null || httpRequest.getRequestedSessionId().equals(httpSession.getId()))
101                        throw SecurityServiceException.newSessionExpiredException("Session expired");
102                }
103                throw SecurityServiceException.newNotLoggedInException("User not logged in");
104            }
105    
106            Request request = httpRequest instanceof Request ? (Request)httpRequest : HttpConnection.getCurrentConnection().getRequest();
107            UserRealm realm = request.getUserRealm();
108            if (reauth)
109                realm.reauthenticate(principal);
110    
111            // Check destination access
112            if (context.getDestination().isSecured()) {
113                boolean accessDenied = true;
114                for (String role : context.getDestination().getRoles()) {
115                    if (realm.isUserInRole(principal, role)) {
116                        accessDenied = false;
117                        break;
118                    }
119                }
120                if (accessDenied)
121                    throw SecurityServiceException.newAccessDeniedException("User not in required role");
122    
123                request.setAuthType(AUTH_TYPE);
124                request.setUserPrincipal(principal);
125            }
126    
127            try {
128                return endAuthorization(context);
129            } catch (InvocationTargetException e) {
130                for (Throwable t = e; t != null; t = t.getCause()) {
131                    if (t instanceof SecurityException)
132                        throw SecurityServiceException.newAccessDeniedException(t.getMessage());
133                }
134                throw e;
135            }
136        }
137    
138    
139        public void logout() throws SecurityServiceException {
140            HttpGraniteContext graniteContext = (HttpGraniteContext)GraniteContext.getCurrentInstance();
141            HttpServletRequest httpRequest = graniteContext.getRequest();
142            Request request = httpRequest instanceof Request ? (Request)httpRequest : HttpConnection.getCurrentConnection().getRequest();
143            UserRealm realm = request.getUserRealm();
144    
145            realm.disassociate(httpRequest.getUserPrincipal());
146            
147            endLogout();
148        }
149    }