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 021package org.granite.messaging.service.security; 022 023import java.lang.reflect.InvocationTargetException; 024import java.security.Principal; 025import java.util.Map; 026 027import javax.servlet.http.HttpServletRequest; 028import javax.servlet.http.HttpSession; 029 030import org.granite.context.GraniteContext; 031import org.granite.messaging.webapp.HttpGraniteContext; 032import org.mortbay.jetty.HttpConnection; 033import org.mortbay.jetty.Request; 034import org.mortbay.jetty.security.UserRealm; 035 036/** 037 * @author William DRAI 038 */ 039public 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, String charset) throws SecurityServiceException { 054 String[] decoded = decodeBase64Credentials(credentials, charset); 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, charset); 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}