Is there a way to configure Tomcat 7 to create JSESSIONID cookie with a secure flag in all occasions?
Usual configuration results in Tomcat flagging session cookie with secure flag only if connection is made through https. However in my production scenario, Tomcat is behind a reverse proxy/load balancer which handles (and terminates) the https connection and contacts tomcat over http.
Can I somehow force secure flag on session cookie with Tomcat, even though connection is made through plain http?
In the end, contrary to my initial tests, web.xml solution worked for me on Tomcat 7.
E.g. I added this snippet to web.xml and it marks session cookie as secure even when reverse proxy contacts tomcat over plain HTTP.
<session-config>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
ServletContext.getSessionCookieConfig().setSecure(true)
Another approach, similar to Mark's, would be to use the SessionCookieConfig, but set it in a context listener from JNDI configuration:
The code:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.SessionCookieConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JndiSessionCookieConfigListener implements ServletContextListener {
private static final Logger logger = LoggerFactory.getLogger( JndiSessionCookieConfigListener.class );
private volatile Context jndiSessionCookieConfig;
private volatile SessionCookieConfig sessionCookieConfig;
#Override
public void contextInitialized( ServletContextEvent sce ) {
String listenerName = getClass().getSimpleName();
try {
logger.info( "JNDI override session cookie config found for {}", listenerName );
jndiSessionCookieConfig = (Context) new InitialContext().lookup(
"java:comp/env/" + listenerName );
}
catch ( NamingException e ) {
logger.info( "No JNDI override session cookie config found for {}", listenerName );
}
sessionCookieConfig = sce.getServletContext().getSessionCookieConfig();
String comment = getString( "comment" );
if ( comment != null ) {
logger.debug( "\t[comment]: [{}]", comment );
sessionCookieConfig.setComment( comment );
}
String domain = getString( "domain" );
if ( domain != null ) {
logger.debug( "\t[domain]: [{}]", domain );
sessionCookieConfig.setDomain( domain );
}
Boolean httpOnly = getBoolean( "http-only" );
if ( httpOnly == null ) {
sessionCookieConfig.setHttpOnly( true );
}
else {
logger.debug( "\t[http-only]: [{}]", httpOnly );
sessionCookieConfig.setHttpOnly( httpOnly );
}
Integer maxAge = getInteger( "max-age" );
if ( maxAge != null ) {
sessionCookieConfig.setMaxAge( maxAge );
}
String name = getString( "name" );
if ( name != null ) {
logger.debug( "\t[name]: [{}]", name );
sessionCookieConfig.setName( name );
}
String path = getString( "path" );
if ( path != null ) {
logger.debug( "\t[path]: [{}]", path );
sessionCookieConfig.setPath( path );
}
Boolean secure = getBoolean( "secure" );
if ( secure == null ) {
sessionCookieConfig.setSecure( true );
}
else {
logger.debug( "\t[secure]: [{}]", secure );
sessionCookieConfig.setSecure( secure );
}
}
#Override
public void contextDestroyed( ServletContextEvent sce ) {
}
private Boolean getBoolean( String name ) {
Object value;
try {
value = jndiSessionCookieConfig.lookup( name );
if ( value instanceof Boolean ) {
return (Boolean)value;
}
else {
return Boolean.valueOf( value.toString() );
}
}
catch ( NamingException e ) {
return null;
}
}
private Integer getInteger( String name ) {
Object value;
try {
value = jndiSessionCookieConfig.lookup( name );
if ( value instanceof Integer ) {
return (Integer)value;
}
else {
return Integer.valueOf( value.toString() );
}
}
catch ( NamingException e ) {
return null;
}
}
private String getString( String name ) {
Object value;
try {
value = jndiSessionCookieConfig.lookup( name );
return value.toString();
}
catch ( NamingException e ) {
return null;
}
}
}
Inside web.xml:
...
<listener>
<listener-class>
org.mitre.caasd.servlet.init.JndiSessionCookieConfigListener
</listener-class>
</listener>
...
In your context.xml:
...
<Environment name="JndiSessionCookieConfigListener/secure"
type="java.lang.String"
override="false"
value="true" />
...
This allows you to set all the session cookie configurations at runtime in the deployment environment. Thus, you could use the same webapp (war file) to do development locally (where you would not have https) and in production where you would ALWAYS want https.
Note, this approach is mentioned in the OWASP documentation
Related
(Sorry for my english)
I am developing a web application with php and Facebook php sdk 4.0. I'm using the FacebookRedirectLoginHelper.php to let the authorize access to their information. I take their facebook-id and store it in the database table Users {int UserID FK, nvarchar(max) UserName, nvarchar(max) facebook-id}. I want to make a list of their facebookfriends who are using the web application. How can this be possible? I can't just change the row:
new FacebookRequest( $session, 'GET', '/me' );
to
new FacebookRequest( $session, 'GET', '/me/friends' );
?
require_once( 'Facebook/FacebookSession.php' );
require_once( 'Facebook/FacebookRedirectLoginHelper.php' );
require_once( 'Facebook/FacebookRequest.php' );
require_once( 'Facebook/FacebookResponse.php' );
require_once( 'Facebook/FacebookSDKException.php' );
require_once( 'Facebook/FacebookRequestException.php' );
require_once( 'Facebook/FacebookAuthorizationException.php' );
require_once( 'Facebook/GraphObject.php' );
use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
// init app with app id (APPID) and secret (SECRET)
FacebookSession::setDefaultApplication('XXX','XXX');
// login helper with redirect_uri
$helper = new FacebookRedirectLoginHelper( 'http://livescoreapp.azurewebsites.net/' );
try {
$session = $helper->getSessionFromRedirect();
} catch( FacebookRequestException $ex ) {
// When Facebook returns an error
} catch( Exception $ex ) {
// When validation fails or other local issues
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>Welcome</h1>
<?php
if($conn === false)
{
die(print_r(sqlsrv_errors()));
}
else //Connection to database is ok.
{
// see if we have a session
if ( isset( $session ) )
{
// graph api request for user data
$request = new FacebookRequest( $session, 'GET', '/me' );
$response = $request->execute();
// get response
$graphObject = $response->getGraphObject();
// print data
echo '<pre>' . print_r( $graphObject, 1 ) . '</pre>';
$fb_Id = $graphObject->getProperty('id');
$fb_Name = $graphObject->getProperty('name');
echo "HEY <a href='" . $fb_link . "'>" . $fb_Name . "</a>";
echo "<br> Your fb-id: " . $fb_Id;
// if(CheckIfUserExistsInDatabase($fb_Id, $conn) == false)
// {
// InsertNewUser($conn, $fb_Id, $fb_Name);
// }
}
else {
// show login url
echo 'Login';
}
}
?>
What this code prints out:
!
To get the user's friends, you must request the user_friends permission when logging the user in:
$loginUrl = $helper->getLoginUrl( array( 'user_friends' ) );
Then, you'll be able to call the API as follows:
$friends = (new FacebookRequest( $session, 'GET', '/me/friends' ))->execute()->getGraphObject()->asArray();
echo '<pre>' . print_r( $friends, 1 ) . '</pre>';
See my tutorial for a complete solution.
The full solution then:
<?php
// added in v4.0.5
require_once( 'Facebook/FacebookHttpable.php' );
require_once( 'Facebook/FacebookCurl.php' );
require_once( 'Facebook/FacebookCurlHttpClient.php' );
// added in v4.0.0
require_once( 'Facebook/FacebookSession.php' );
require_once( 'Facebook/FacebookRedirectLoginHelper.php' );
require_once( 'Facebook/FacebookRequest.php' );
require_once( 'Facebook/FacebookResponse.php' );
require_once( 'Facebook/FacebookSDKException.php' );
require_once( 'Facebook/FacebookRequestException.php' );
require_once( 'Facebook/FacebookOtherException.php' );
require_once( 'Facebook/FacebookAuthorizationException.php' );
require_once( 'Facebook/GraphObject.php' );
require_once( 'Facebook/GraphSessionInfo.php' );
// added in v4.0.5
use Facebook\FacebookHttpable;
use Facebook\FacebookCurl;
use Facebook\FacebookCurlHttpClient;
// added in v4.0.0
use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookOtherException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\GraphSessionInfo;
// start session
session_start();
// init app with app id and secret
FacebookSession::setDefaultApplication( 'XXX','YYY' );
// login helper with redirect_uri
$helper = new FacebookRedirectLoginHelper( 'http://livescoreapp.azurewebsites.net/' );
// see if a existing session exists
if ( isset( $_SESSION ) && isset( $_SESSION['fb_token'] ) ) {
// create new session from saved access_token
$session = new FacebookSession( $_SESSION['fb_token'] );
// validate the access_token to make sure it's still valid
try {
if ( !$session->validate() ) {
$session = null;
}
} catch ( Exception $e ) {
// catch any exceptions
$session = null;
}
} else {
// no session exists
try {
$session = $helper->getSessionFromRedirect();
} catch( FacebookRequestException $ex ) {
// When Facebook returns an error
} catch( Exception $ex ) {
// When validation fails or other local issues
echo $ex->message;
}
}
// see if we have a session
if ( isset( $session ) ) {
// save the session
$_SESSION['fb_token'] = $session->getToken();
// create a session using saved token or the new one we generated at login
$session = new FacebookSession( $session->getToken() );
// graph api request for user data
$friends = (new FacebookRequest( $session, 'GET', '/me/friends' ))->execute()->getGraphObject()->asArray();
echo '<pre>' . print_r( $friends, 1 ) . '</pre>';
// print logout url using session and redirect_uri (logout.php page should destroy the session)
echo 'Logout';
} else {
// show login url
echo 'Login';
}
?>
See the 90 line in FacebookRedirectLoginHelper.php .... it looks like
public function getLoginUrl($scope = array(), $version = null)
I change by
public function getLoginUrl($scope = array('email'), $version = null)
and works!!! PD. Put in &scope array the permissions you need.
Regards!!!
$fb = new Facebook\Facebook([/* . . . */]);
$helper = $fb->getRedirectLoginHelper();
$permissions = ['email', 'user_likes']; // optional
$loginUrl = $helper->getLoginUrl('http://{your-website}/login-callback.php', $permissions);
echo 'Log in with Facebook!';
I have a bundle with just a cover that i have inserted in my timeline using mirror API. Now what i want is when a user clicks on the bundle, i get a custom menu clicking on which the backend is called to insert a set of cards again in the same bundle.
public class newsfeedbliss {
static String bundleId = "lunchRoulette" + UUID.randomUUID();
private static ArrayList<String> newstext = new ArrayList<String>();
static final String PROD_BASE_URL = "https://newsfeedbliss.appspot.com";
private static final String PROD_CALLBACK = PROD_BASE_URL + "/newsfeedcallback";
private static final String TEST_CALLBACK = "https://newsfeedbliss.appspot.com/newsfeedcallback";
public static void subscribe( HttpServletRequest req, String userId )
throws IOException
{
Mirror mirror = MirrorUtils.getMirror( req );
// START:subscribe
final String callbackUrl = "https://newsfeedbliss.appspot.com/newsfeedcallback";
Subscription tliSubscription = new Subscription()
.setCallbackUrl( callbackUrl )
.setVerifyToken( "a_secret_to_everybody" )
.setUserToken( userId )
.setCollection( "timeline" )
.setOperation( Collections.singletonList( "UPDATE" ) );
mirror.subscriptions().insert( tliSubscription ).execute();
// END:subscribe
// TODO: check if this user has subscribed, skip if already has
SubscriptionsListResponse subscriptions = mirror.subscriptions().list().execute();
for (Subscription sub : subscriptions.getItems()) {
System.out.println( sub );
}
}
public static TimelineItem buildarticlestimeline(
ServletContext ctx, String userId )
throws IOException, ServletException, ParserConfigurationException, SAXException
{
Mirror mirror = MirrorUtils.getMirror( userId );
Timeline timeline1 = mirror.timeline();
TimelineItem timelineItem1 = new TimelineItem()
.setText("Hello");
timeline1.insert( timelineItem1 ).executeAndDownloadTo( System.out );
return timelineItem1;
}
public static void insertSimpleTextTimelineItem( HttpServletRequest req )
throws IOException, ParserConfigurationException, SAXException
{
Mirror mirror = MirrorUtils.getMirror( req );
Timeline timeline = mirror.timeline();
TimelineItem timelineItem = new TimelineItem()
.setHtml("<article>\n <section>\n <p class=\"text-auto-size\">This <em class=\"yellow\">paragraph</em> auto-resizes according to the <strong class=\"blue\">HTML</strong> content length.\n </p>\n </section>\n</article>\n")
.setBundleId(bundleId)
.setIsBundleCover(true);
setSimpleMenuItems(timelineItem,true);
timeline.insert( timelineItem ).executeAndDownloadTo( System.out );
System.out.println("Hello hello");
}
public static void setSimpleMenuItems( TimelineItem ti, boolean hasRestaurant ) {
// Add blank menu list
ti.setMenuItems( new LinkedList<MenuItem>() );
ti.getMenuItems().add( new MenuItem().setAction( "READ_ALOUD" ) );
ti.getMenuItems().add( new MenuItem().setAction( "DELETE" ) );
List<MenuValue> menuValues = new ArrayList<MenuValue>(2);
menuValues.add( new MenuValue()
.setState( "DEFAULT" )
.setDisplayName( "Alternative" )
// .setIconUrl( "" )
);
menuValues.add( new MenuValue()
.setState( "PENDING" )
.setDisplayName( "Generating Alternative" ) );
ti.getMenuItems().add( new MenuItem()
.setAction( "CUSTOM" )
.setId( "ALT" )
.setPayload( "ALT" )
.setValues( menuValues )
);
}
}
This is my servlet file
public class NewsfeedblissServlet extends HttpServlet
{
private static final Logger log = Logger.getLogger(NewsfeedblissServlet.class.getName());
/** Accept an HTTP GET request, and write a random lunch type. */
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException
{
log.info("in do get");
try {
newsfeedbliss.insertSimpleTextTimelineItem( req );
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.info("called insert text");
resp.setContentType("text/html");
resp.getWriter().append( "Inserted Timeline Item" );
}
}
And this is the class i have written that has the code that i want to run on callback that detects custom menu click and inserts the cards.
public class TimelineUpdateServlet extends HttpServlet
{
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
System.out.println("Hey, Hello");
res.getWriter().append( "Inside update servlet" );
// Generate Notification from request body
JsonFactory jsonFactory = new JacksonFactory();
Notification notification =
jsonFactory.fromInputStream( req.getInputStream(), Notification.class );
// Get this user action's type
String userActionType = null;
if( !notification.getUserActions().isEmpty() )
userActionType = notification.getUserActions().get(0).getType();
//If this is a pinned timeline item, log who and which timeline item
if( "timeline".equals( notification.getCollection() )
&& "UPDATE".equals( notification.getOperation() )
&& "CUSTOM".equals( userActionType ) )
{
UserAction userAction = notification.getUserActions().get(0);
if( "ALT".equals( userAction.getPayload() ) )
{
// Add a new timeline item, and bundle it to the previous one
String userId = notification.getUserToken();
String itemId = notification.getItemId();
Mirror mirror = MirrorUtils.getMirror( userId );
Timeline timeline = mirror.timeline();
// Get the timeline item that owns the tapped menu
TimelineItem current = timeline.get( itemId ).execute();
String bundleId = current.getBundleId();
// If not a bundle, update this item as a bundle
if( bundleId == null ) {
bundleId = "lunchRoulette" + UUID.randomUUID();
current.setBundleId( bundleId );
timeline.update( itemId, current).execute();
}
// Create a new random restaurant suggestion
TimelineItem newTi=null;
try {
newTi = newsfeedbliss.buildarticlestimeline( getServletContext(), userId );
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
newTi.setBundleId( bundleId );
timeline.insert( newTi ).execute();
}
}
}
}
In your TimelineUpdateServlet code you must modify your original item to setIsBundleCover(true). The bundle cover will not have any menu items as it only acts as a parent for the items below it. Thus call
current.setIsBundleCover(true);
before you call
timeline.update( itemId, current).execute();
This should allow the new card to appear in the bundle properly.
I am trying to use the Mojarra JSF 2 compiler programatically with a view to checking the correctness of the xhtml of any pages.
I have got so far but the compiler is not erroring for tags that don't exist in a particular tag library. It does the standard XML namespace checks but if say rich:spacer is present it should error (it got removed in Richfaces 4.x). At runtime this check takes does take place.
Any thoughts? Here is my code:
#RunWith( PowerMockRunner.class )
#PrepareForTest( { WebConfiguration.class, FacesContext.class } )
public class XhtmlValidatorTest
{
#Test
public void test() throws IOException
{
WebConfiguration webConfiguration = PowerMock.createMock( WebConfiguration.class );
PowerMock.mockStatic( WebConfiguration.class );
WebConfiguration.getInstance();
PowerMock.expectLastCall().andReturn( webConfiguration ).anyTimes();
FaceletsConfiguration faceletsConfiguration = PowerMock.createMock( FaceletsConfiguration.class );
webConfiguration.getFaceletsConfiguration();
PowerMock.expectLastCall().andReturn( faceletsConfiguration ).anyTimes();
faceletsConfiguration.isProcessCurrentDocumentAsFaceletsXhtml(EasyMock.isA( String.class ) );
PowerMock.expectLastCall().andReturn(true).anyTimes();
faceletsConfiguration.isConsumeComments( EasyMock.isA( String.class) );
PowerMock.expectLastCall().andReturn(false).anyTimes();
faceletsConfiguration.isConsumeCDATA( EasyMock.isA( String.class ) );
PowerMock.expectLastCall().andReturn(false).anyTimes();
webConfiguration.isOptionEnabled(BooleanWebContextInitParameter.EnableMissingResourceLibraryDetection);
PowerMock.expectLastCall().andReturn( false ).anyTimes();
webConfiguration.isOptionEnabled(BooleanWebContextInitParameter.EnableCoreTagLibraryValidator );
PowerMock.expectLastCall().andReturn( true ).anyTimes();
FacesContext facesContext = PowerMock.createMock( FacesContext.class );
PowerMock.mockStatic( FacesContext.class );
FacesContext.getCurrentInstance();
PowerMock.expectLastCall().andReturn( facesContext ).anyTimes();
facesContext.isProjectStage( ProjectStage.Development );
PowerMock.expectLastCall().andReturn( false ).anyTimes();
Application application = PowerMock.createMock( Application.class );
facesContext.getApplication();
PowerMock.expectLastCall().andReturn( application ).anyTimes();
application.getExpressionFactory();
PowerMock.expectLastCall().andReturn( new org.jboss.el.ExpressionFactoryImpl() ).anyTimes();
PowerMock.replayAll();
long refreshPeriod = -1;
com.sun.faces.facelets.compiler.Compiler compiler = new SAXCompiler();
compiler.setValidating( true );
System.out.println( "Compiler.isValidating() " + compiler.isValidating() );
FaceletCache cache = new UnittestFaceletCacheFactory().getCache( refreshPeriod );
ResourceResolver resolver = new ResourceResolver()
{
#Override
public URL resolveUrl(String path)
{
URL url = null;
try
{
url = new URL( BASE_PATH + path );
}
catch (MalformedURLException e)
{
throw new RuntimeException( e );
}
return url;
}
};
DefaultFaceletFactory defaultFaceletFactory = new DefaultFaceletFactory( compiler, resolver, refreshPeriod, cache );
File file = new File( "WebContent" );
File[] files = file.listFiles();
for( File xhtmlFile : files )
{
if( xhtmlFile.isFile() )
{
String name = xhtmlFile.getName();
if( name.endsWith(".xhtml" ) )
{
System.out.println( "compiling: " + name );
defaultFaceletFactory.getFacelet( name );
}
}
}
}
The facelet cache factory used in the code is a hack:
package com.sun.faces.facelets.impl;
import javax.faces.view.facelets.FaceletCache;
public class UnittestFaceletCacheFactory
{
public FaceletCache getCache( long refreshPeriod )
{
return new DefaultFaceletCache( refreshPeriod );
}
}
Since it' apparently not possible to authenticate with LDAP on my BlackBerry App, I'm trying to use a kind of workaround. Instead of authenticate directly on the LDAP Server, I want to use a Web Service in between. So it looks like this
App --calls--> Web Service --calls--> LDAP Server
So the Web Service should take the username and password given from the Application and send it to the LDAP Server. If its possible to sign in, the Web Service gets a TRUE as response and forward it to the App.
That's how it should work. But at the moment, when I call the Web Service from the App, I get following error:
SoapFault - faultcode: 'S:Server' faultstring:
'java.lang.NullPointerException' faultactor: 'null' detail:
org.kxml2.kdom.Node#21e05a11
Seems like a Server problem but I don't know where :(
Well, that's the Web Service I'm using:
import javax.ejb.Stateless;
import javax.jws.WebService;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPException;
#Stateless
#WebService()
public class ldapServiceBean implements ldapService {
#Override
public String error() {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean ldapLogin(String username, String password) {
int ldapPort = LDAPConnection.DEFAULT_PORT;
int ldapVersion = LDAPConnection.LDAP_V3;
String ldapHost = "dc1.somehost ";
String loginDN =
"CN="+username+",OU=employee,OU=user,DC=somehost";
byte[] passwordBytes = password.getBytes();
LDAPConnection lc = new LDAPConnection();
try {
// connect to the server
lc.connect( ldapHost, ldapPort );
// authenticate to the server
lc.bind( ldapVersion, loginDN, passwordBytes );
System.out.println("Bind successful");
return true;
}
catch( LDAPException e ) {
if ( e.getResultCode() == LDAPException.NO_SUCH_OBJECT ) {
System.err.println( "Error: No such entry" );
} else if ( e.getResultCode() ==
LDAPException.NO_SUCH_ATTRIBUTE ) {
System.err.println( "Error: No such attribute" );
} else {
System.err.println( "Error: " + e.toString() );
}
}
return false;
}
And that's the method calling the Web Service
private static final String SOAP_ACTION = "";
private static final String METHOD_NAME = "ldapLogin";
private static final String NAMESPACE = "http://ldapproxy.somehost/";
private static final String URL = "http://myIP:8080/LDAPProxy/ldapServiceBeanService";
...
public boolean login(String username, String password) {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
//SoapObject
request.addProperty("username", username);
request.addProperty("password", password);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
//envelope.dotNet = true;
//envelope.bodyOut = request;
envelope.setOutputSoapObject(request);
HttpTransport httpTransport = new HttpTransport(URL);
try
{
httpTransport.call(SOAP_ACTION, envelope);
System.out.println("request: " + httpTransport.requestDump);
resultsRequestSOAP = (SoapObject) envelope.getResponse();
return true;
}catch(SoapFault sF){
String error = sF.toString();
Dialog.alert(error);
}
catch (Exception aE)
{
Dialog.alert("Connection failed");
aE.printStackTrace ();
}
return false;
}
What I found out so far:
It seems that the webservice don't receives the username and password property. As I print them I get:
`CN=null, OU=employee, OU=...`
Like I've read at this post Web service recieves null parameters from application using ksoap method it seems ksoap have a problem with colons. I changed my NAMESPACE but without any success. Maybe I need to change my URL too. But how would I do this while I still need to use localhost ?
As always when doing LDAP bind testing this way, recall that the standard requires that a bind of a username, no password, is a successful Anonymous bind, so therefore you MUST validate for this case (empty password) on login attempts.
I'm doing some maintenance on an older web application written in Monorail v1.0.3. I want to unit test an action that uses RenderText(). How do I extract the content in my test? Reading from controller.Response.OutputStream doesn't work, since the response stream is either not setup properly in PrepareController(), or is closed in RenderText().
Example Action
public DeleteFoo( int id )
{
var success= false;
var foo = Service.Get<Foo>( id );
if( foo != null && CurrentUser.IsInRole( "CanDeleteFoo" ) )
{
Service.Delete<Foo>( id );
success = true;
}
CancelView();
RenderText( "{ success: " + success + " }" );
}
Example Test (using Moq)
[Test]
public void DeleteFoo()
{
var controller = new FooController ();
PrepareController ( controller );
var foo = new Foo { Id = 123 };
var mockService = new Mock < Service > ();
mockService.Setup ( s => s.Get<Foo> ( foo.Id ) ).Returns ( foo );
controller.Service = mockService.Object;
controller.DeleteTicket ( foo.Id );
mockService.Verify ( s => s.Delete<Foo> ( foo.Id ) );
Assert.AreEqual ( "{success:true}", GetResponse ( Response ) );
}
// response.OutputStream.Seek throws an "System.ObjectDisposedException: Cannot access a closed Stream." exception
private static string GetResponse( IResponse response )
{
response.OutputStream.Seek ( 0, SeekOrigin.Begin );
var buffer = new byte[response.OutputStream.Length];
response.OutputStream.Read ( buffer, 0, buffer.Length );
return Encoding.ASCII.GetString ( buffer );
}
Override BaseControllerTest.BuildResponse() and provide your mock of IMockResponse built with Moq.