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 }