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.security.auth.login.LoginException;
028import javax.servlet.http.HttpServletRequest;
029import javax.servlet.http.HttpServletResponse;
030import javax.servlet.http.HttpSession;
031
032import org.granite.context.GraniteContext;
033import org.granite.messaging.webapp.HttpGraniteContext;
034
035import weblogic.servlet.security.ServletAuthentication;
036
037/**
038 * @author Franck WOLFF
039 */
040public class WebLogicSecurityService extends AbstractSecurityService {
041
042    public WebLogicSecurityService() {
043    }
044
045    public void configure(Map<String, String> params) {
046    }
047
048    public void login(Object credentials, String charset) throws SecurityServiceException {
049        String[] decoded = decodeBase64Credentials(credentials, charset);
050
051        HttpGraniteContext context = (HttpGraniteContext)GraniteContext.getCurrentInstance();
052        HttpServletRequest httpRequest = context.getRequest();
053        HttpServletResponse httpResponse = context.getResponse();
054
055        int result = ServletAuthentication.FAILED_AUTHENTICATION;
056        try {
057                result = ServletAuthentication.login(decoded[0], decoded[1], httpRequest, httpResponse);
058        }
059        catch (LoginException e) {
060        }
061        if (result != ServletAuthentication.AUTHENTICATED)
062                throw SecurityServiceException.newInvalidCredentialsException("Wrong username or password");
063        
064        // Make sure we have a valid HTTP session.
065        httpRequest.getSession(true);
066        
067        endLogin(credentials, charset);
068    }
069
070    public Object authorize(AbstractSecurityContext context) throws Exception {
071
072        startAuthorization(context);
073
074        if (context.getDestination().isSecured()) {
075            HttpGraniteContext graniteContext = (HttpGraniteContext)GraniteContext.getCurrentInstance();
076            HttpServletRequest httpRequest = graniteContext.getRequest();
077
078            Principal principal = httpRequest.getUserPrincipal();
079            if (principal == null && tryRelogin())
080                principal = httpRequest.getUserPrincipal();
081            
082            if (principal == null) {
083                if (httpRequest.getRequestedSessionId() != null) {
084                    HttpSession httpSession = httpRequest.getSession(false);
085                    if (httpSession == null || httpRequest.getRequestedSessionId().equals(httpSession.getId()))
086                        throw SecurityServiceException.newSessionExpiredException("Session expired");
087                }
088                throw SecurityServiceException.newNotLoggedInException("User not logged in");
089            }
090            
091            boolean accessDenied = true;
092            for (String role : context.getDestination().getRoles()) {
093                if (httpRequest.isUserInRole(role)) {
094                    accessDenied = false;
095                    break;
096                }
097            }
098            if (accessDenied)
099                throw SecurityServiceException.newAccessDeniedException("User not in required role");
100        }
101
102        try {
103            return endAuthorization(context);
104        } catch (InvocationTargetException e) {
105            for (Throwable t = e; t != null; t = t.getCause()) {
106                // Don't create a dependency to javax.ejb in SecurityService...
107                if (t instanceof SecurityException ||
108                    "javax.ejb.EJBAccessException".equals(t.getClass().getName()))
109                    throw SecurityServiceException.newAccessDeniedException(t.getMessage());
110            }
111            throw e;
112        }
113    }
114
115    public void logout() throws SecurityServiceException {
116        HttpGraniteContext graniteContext = (HttpGraniteContext)GraniteContext.getCurrentInstance();
117        HttpServletRequest httpRequest = graniteContext.getRequest();
118
119        endLogout();
120        
121        // Make sure we invalidate current HTTP session.
122        if (httpRequest.getSession(false) != null)
123                httpRequest.getSession().invalidate();
124
125        ServletAuthentication.logout(httpRequest);
126    }
127}