Oracle9iAS Portal Developer Kit (PDK)
Implementing Security Services in PL/SQL Portlets

Last Update: Aug 04, 2003
Status: Production
Version: Any PDK Release

Introduction

Oracle9iAS Portal provides a set of APIs for the security mechanism that the PL/SQL portlets typically use. Portlet security refers to the techniques and methods used by portlets to control their access to end users. For an introductory overview of Security Services, please refer to the Primer on Security Services.

Oracle9iAS Portal strictly controls access to information and applications. This is accomplished by assigning specific privileges to users and groups. Portal security services allow you to specify access control programmatically and check for the appropriate privileges at runtime. The security mechanisms used by portlets ensure that only authorized users will have access to these portlets.

Security services are available through the wwsec_api package.

This article describes how the security services are implemented using the Services Example. It provides a guideline for adding the security service to your portlet functionality.

Assumptions

How to use Security Service

The portal requires the method is_portlet_runnable to be implemented by database providers. This method implements portlet security. The actual implementation of this method is up to the application to be specified, i.e. the security scheme that determines whether or not the current user has enough privileges to access the portlet is defined by the individual portlet implementation.

The portal also requires the method get_portlet_list for database providers to return the right set of portlets that are accessible by the currently logged on user.

Implementing Security Service

This section describes how the security service is implemented for the Services Example.
  1. From the downloaded Services Example, review the Provider file (services_provider.pkb) which is the package body of the Provider. An excerpt is provided below.
  2. Scroll to the section that contains the procedure is_portlet_runnable. This function in turn calls the security implementation of the portlet through the portlet's is_runnable function to check portlet access privileges.

    CREATE OR REPLACE

    package body SERVICES_PROVIDER

    is

    function is_portlet_runnable

    (

    p_portlet_instance in wwpro_api_provider.portlet_instance_record

    )

    return boolean

    is

    begin

    if (p_portlet_instance.portlet_id = SERVICES_PORTLET_ID) then

    return services_portlet.is_runnable(

    p_provider_id => p_portlet_instance.provider_id

    ,p_reference_path => p_portlet_instance.reference_path

    );

    else

    raise wwpro_api_provider.PORTLET_NOT_FOUND_EXCEPTION;

    end if;

    end is_portlet_runnable;

    ...

    end SERVICES_PROVIDER;

    /

  3. Scroll to the section that contains the procedure get_portlet_list. The get_portlet_list allows the portlet to be included in the portlet list that represents the portlets implemented by this provider. The get_portlet_list first checks the security flag (p_security_level) to find out whether security is enabled. Only when the flag is set to true, it checks for is_runnable to check portlet access before calling the get_portlet function. The value of the p_security_level parameter indicates whether security checks will be performed to determine whether a portlet will be returned in the list. When a portlet repository refresh operation retrieves the master list of portlets implemented by the provider, the parameter p_security_level has a value of false. A value of false indicates to the provider that no portlet security check should be made and that a master list of all of the portlets implemented by the provider must be returned. The master list of portlets returned is used to populate the portlet repository for that provider. If the value of p_security_level is true, then it is up to the provider implementation to decide whether portlet security should be performed. If portlet security is implemented, the provider may return a different list of portlets depending on the currently logged on user.

    CREATE OR REPLACE

    package body SERVICES_PROVIDER

    is

    ...

    function get_portlet_list (

    p_provider_id in integer

    ,p_start_row in integer

    ,p_rowcount in integer

    ,p_language in varchar2

    ,p_security_level in boolean

    ,p_type in integer

    )

    return wwpro_api_provider.portlet_table

    is

    l_portlet_list wwpro_api_provider.portlet_table;

    l_cnt number;

    begin

    l_cnt := 0;

    if (p_security_level = false) then

    l_cnt := l_cnt + 1;

    l_portlet_list(l_cnt) := get_portlet(

    p_provider_id => p_provider_id

    ,p_portlet_id => SERVICES_PORTLET_ID

    ,p_language => p_language

    );

    return l_portlet_list;

    end if;


    if (services_portlet.is_runnable(

    p_provider_id => p_provider_id

    ,p_reference_path => null)

    ) then

    l_cnt := l_cnt + 1;

    l_portlet_list(l_cnt) := get_portlet(

    p_provider_id => p_provider_id

    ,p_portlet_id => SERVICES_PORTLET_ID

    ,p_language => p_language

    );

    end if;

    return l_portlet_list;

    end get_portlet_list;

    ...

    end SERVICES_PROVIDER;

    /

  4. From the downloaded Services Example, review the services_portlet.pkb file which is the package body for this portlet. An excerpt is provided below.
  5. Scroll the file to the section that contains the procedure get_portlet_info. The portlet performs the security check of calling is_runnable here, and on detecting that the portlet is not accessible by current user, logs an error condition.

    CREATE OR REPLACE

    package body SERVICES_PORTLET

    is

    ...

    function get_portlet_info

    (

    p_provider_id in integer

    ,p_language in varchar2

    )

    return wwpro_api_provider.portlet_record

    is

    l_portlet wwpro_api_provider.portlet_record;

    begin

    -- Perform the Security Check

    if not is_runnable(p_provider_id, null)

    then

    wwerr_api_error.add(DOMAIN, SUBDOMAIN,

    'securityerr', 'services_portlet.get_portlet_info');

    raise wwpro_api_provider.PROVIDER_SECURITY_EXCEPTION;

    end if;

    ...

    end SERVICES_PORTLET;

    /

  6. Now scroll to the section where the is_runnable procedure is defined. This security implementation for allowing portlet access checks that the user is logged on by calling the wwctx_api.is_logged_on API. You can choose to have your own security implementation functionality. The is_runnable is called from the show procedure too, as shown below.

    CREATE OR REPLACE

    package body SERVICES_PORTLET

    is

    function is_runnable (

    p_provider_id in integer

    ,p_reference_path in varchar2

    )

    return boolean

    is

    begin

    /*

    Portlet security check. It allows the portlet to be visible

    if the user is logged on, i.e. the current session is not a

    public session.

    */

    return wwctx_api.is_logged_on;

    end is_runnable;

    ...

    procedure show

    (

    p_portlet_record wwpro_api_provider.portlet_runtime_record

    )

    is

    l_portlet wwpro_api_provider.portlet_record;

    begin

    -- Perform the Security Check

    if not is_runnable(p_provider_id, null)

    then

    wwerr_api_error.add(DOMAIN, SUBDOMAIN,

    'securityerr', 'services_portlet.show');

    raise wwpro_api_provider.PROVIDER_SECURITY_EXCEPTION;

    end if;

    end show;

    ...

    end SERVICES_PORTLET;

    /

You can implement security service in a similar fashion but based on your functional requirements.

View Portlet functionality

  1. Create a page and add the Services portlet to your page. View your page while logged in. Copy the URL of your page onto the clipboard. Log out of your Oracle Portal session. Now try to view the same page using the previously copied URL. Take note of how the the security service prevents you from viewing your page.
Revision History:
Revision No Last Update
1.0

Dec 15, 2000


Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065, USA
http://www.oracle.com/
Worldwide Inquiries:
1-800-ORACLE1
Fax 650.506.7200
Copyright and Corporate Info