Transcript
00:01Thanks, everybody, for showing up. Just a couple of items to note.
00:06So all the code and different things that I'm showing today I have available; I guess I'll try to put it up on GitHub...
00:12...but I have my e-mail there if you want me to send it to you. There's no issues with that.
00:18Also I went to...did anybody go through the DTS Agile presentation, four presentations yesterday?
00:25So I went there and then I changed my entire presentation based upon the stuff that they did.
00:31So if this is your first time seeing this presentation, then we're both in the same boat.
00:38We'll just be going through the slides.
00:39I will be jumping back and forth, to give you some of the coding examples, so we can just start.
00:47Okay, so the problem that I faced was that, you know, the project manager came, and she was like...
00:55...you know, we have all these widgets now that you developed for this particular client...
01:02...but not everybody can access all of those widgets.
01:07And so I tried to think about some of the solutions that could have been implemented, but as I thought about them...
01:18...I just tried to go back to see what is the most scalable design that I could sort of come up with to sort of solve this problem?
01:25So, you know, I don't know the number of users.
01:29I don't know which of those users have access to which widgets, and so pretty much, once this project...
01:37...product is developed, it gets handed over to the client, and everything else is out of my control.
01:45Also the first thing, you know, that I do is go to the forums.
01:50And so I develop with all the web APIs as well as some of the other Esri stack, and, you know, the forums for...
01:58...all the different products across Esri are always very informative, very helpful, and you can get some valuable information.
02:05And even if you really don't find your solution...
02:07...you kind of find some other tidbits of information that you can use for a different project.
02:11So if you don't leverage the Esri forums, I would encourage you to do so.
02:15And so as Flex Viewer developers - I assume the majority of us are Flex Viewer developers...
02:22...once you do go to the forums, the second thing that you do is pray that Robert responds.
02:29'Cause once he responds, you know, life is good; he's already solved your problem.
02:33You know, you get his solution or he'll write a solution and write you back...
02:37...and work with you for 10 days straight if that's what it calls for.
02:41But in this particular case, Robert doesn't do a lot with security and different things like that...
02:48...'cause that's just not what his requirements are, and so I had to come up with something on my own.
02:55And so what are my options now?
02:56Some of the solutions that people suggested were, you know, you can have the ability to use multiple configuration files.
03:05And so I could, one, come up with sort of an elaborate convention by which I can write documentation to the client...
03:13...and say, hey, if you do X, Y, and Z, and if you have a hundred users then create a hundred user - config files...
03:20...and then, you know, life is good for me 'cause that's the most simplest thing because it's already embedded into the Flex Viewer.
03:27But that seems sort of like an arduous task to ask the client to do.
03:32So another thing that I could do was sort of extend a database model...
03:36...and put all my configuration inside the database and do it that way.
03:42One thing about that is the amount of widgets that we had, the amount of other flexibility that we wanted, providing...
03:51...that solution meant that I would have to make a custom app so that way it would be a lot easier for the client to sort of say...
03:58...hey, this user can pick this widget; this user can pick that widget.
04:01And I didn't really have the time to sort of go that route.
04:07And so any of those solutions, I would have had to customize the viewer...
04:13...and so that's primarily what the discussion's going to be about.
04:17At any point in time, we can stop and discuss, or if you have questions, I can answer questions and stuff.
04:25Okay, so the idea was just to provide the user with a place to enter in their user name and password...
04:32...then authenticate that to some back end; it could be a text file...
04:37...it could be a database, it could be another web service, anything.
04:41And then, based upon that, you know, the initial requirement was to provide them various degrees of widgets that they can access.
04:48And so even for group widgets, we can control that nature as well.
04:55So just for the demonstration purposes, I have a SQL Server Express database that I have...
05:02...and that's what I would provide as sort of the back end if somebody requested the database part of this tier solution.
05:12But primarily, what I generally use, is ArcGIS Server's security.
05:17It kind of works well because if I have secured services, then I can just sort of tie that in...
05:23...directly with ArcGIS Server and be done with it.
05:27They also provide an interface for me to add different users and control roles and things of that nature...
05:33...and so in this particular case, the client wanted to manage their services.
05:38They were comfortable with using ArcGIS Manager to control that aspect of it, so that alleviated me...
05:45...from having to write anything custom to provide them an interface to control their users and permissions.
05:54And so besides ArcGIS Server Manager, which is sort of that part up there...
05:59...what that uses in the background is ASP.NET databases, right?
06:03So all you have to do is open up a console, if you have administrative permissions to the database...
06:09...and, you know, type in some command line code, and Microsoft will then create the database for you.
06:19And so they give you all your roles, all your users, your profiles...
06:24...but pretty much what we're going to do is just leverage the users and the roles.
06:33And so for the middle tier, what we did was use ASP.NET web handlers, and because we're using ASP.NET databases...
06:41...in the background, it makes it real simple for us to sort of use the membership provider.
06:48So we just look at the code - that's kind of constrained here.
07:01To log in a user, all I have to do is get the user name and the password from what was requested...
07:08...and then say, hey, membership provider, is this a valid user? Here's the user name and password.
07:14And then the membership provider knows what database that I'm working with based on the web config file...
07:19...goes into that and returns me, hey, this user's valid or, hey, this user is invalid.
07:27And so some of the things that you would want to look out for with that - and I've got to bring my solution explorer back up...
07:34...is that if you're working with IIS 7, you have to make sure that you put your handlers inside the system.web...
07:42...and the system.web handlers.
07:44Other than that, you'll sort of be banging your head against a wall trying to understand...
07:48...how come your web handlers aren't triggering.
08:00And we can look at that a little bit more if somebody needs to look at it.
08:05Okay, so now that we have our back end taken care of and now we have a way to access the data...
08:12...and so the way that we're accessing the data is just through a web service that we just built.
08:17And so if you wanted to scale this out to provide somebody else access to that database...
08:22...based upon whatever your enterprise needs are, they can access the same web services as well.
08:30Okay, so now we get to the part where we have to actually do a lot of the grunt work...
08:35...and that's where modifying the viewer comes into play.
08:39And so for this particular example, I am using the Flex Viewer 2.5, the most recent release...
08:47...and in there, they have Security Manager, and so that hasn't fully been implemented.
08:53I'm pretty sure that's there for when the 3.0 release comes out in ArcGIS 10.1.
08:58Don't quote me on that; I'm not sure. But that's not what I used.
09:01I created something called the Authorization Manager just to sort of not confuse the two.
09:08But for modifying the viewer, these are the different files within the viewer that I had to modify.
09:17And so the ones that are in red are two of the files that I created.
09:21The HTMLPopupLoginRole, that's just to give the user name and password capability...
09:27...and then all the communication with those web services goes through the Authorization Manager.
09:32And then if you ever request the code and you're looking through it, all you have to do is search for...
09:37...add-in for authorization, and it should take you to every part in the code that I had to tweak in order to get the solution function.
09:48Okay, so for the UI, the first thing that I did was to provide the login box as well as for inside the header controller widget...
09:57...I extended that, and so now that have a nice little login clickable area that brings up the dialog.
10:09And then for the actual guts for the viewer, what we had to do was change these files right here...
10:16...so the index file, the config file, the ConfigData file, the ConfigManager file, and the ViewerContainer...
10:21...but once you do all that - and we'll look at what that provides you here in a second - then from the main config file...
10:28...so, you know, config.xml, now you're able to add your own custom tags inside there.
10:35And then once you finally get to the heart of it all, when I'm doing it will show that I'm returning...
10:42...a list of roles that a particular user is within, I just settled on a convention called validGroups...
10:52...and I add that as a new tag to my widgets.
10:55And that's what allows me to filter the widgets, and we'll look at all that here in just a second.
11:04So if you do want to add new tags to your config file, some of the files that you want to manipulate...
11:13...are ConfigData - so in here, I added a bunch of just public variables that account for the URLs that I'm pulling out of that config file.
11:28And then in the configManager class, you want to read that in, you want to read that information in from the XML file.
11:36So here's where you start to read that information in from the XML file and store it as part of the configData class.
11:44And once you do those two things, then they're available to you once the event fires that the configData element is ready...
11:54...and then you can begin to sort of parse that information inside your particular manager class.
11:59And that's what we are doing...inside here, the configLoadedHandler.
12:21So the event fired, and now I have access to those URLs, and that's what I did use in order to access my web services.
12:39Okay. And so for authorization, and that's something that we want to focus on here...
12:47...I have my URL to my login handler, but then when you make a request, one of the things that happened...
12:54...and tripped me up for probably better part of two days, was that the browser would cache my credentials.
13:02So every time I would make a request after the first time, it was authenticated, you know, it would work...
13:09...and then every subsequent time, it would still work.
13:13And I'm trying to bang my head to try to figure out, and finally, you know, after some Google searches...
13:19...then I realized that I had to make a unique request every time.
13:22So putting on this new date or some type of GUID or just making the request unique every time will alleviate...
13:29...a lot of heartache that you may face when making a certain request that could potentially be cached by the browser.
13:40And so once we make our request, then we come back down to our handler for that request...
13:46...and now we have whether or not our user is authenticated, and if they are, then we request the role for that particular user.
13:56So we go here, we send off these parameters, which is the user name and password, and my handler accepts that information...
14:04...and then it sends that to the database using the custom membership - or not the custom membership provider...
14:09...but the membership provider, and then we check whether or not our response is valid.
14:21And so what else can be done besides filtering out the individual widgets?
14:28From there, we could do things like if there is a service that's secured, you know, you can provide that capability...
14:36...and I'll show an example of that.
14:37So when they first log in, they see one set of services, or when they first go to your website, they see one set of services...
14:43...and then after they log in, they can get presented with a new set of services.
14:47Or, you know, you can start to augment the user interface at that point, because now, you know...
14:52...you have a way to authenticate which users can see what elements of the UI or can't see which elements of the UI.
14:58You can also control data access as well.
15:07So as we look into the solution, once we get the individual user back and saying whether or not that's a valid user...
15:18...the crux of the decision handling goes into the header controller widget.
15:28And that's the XML for it, headercontroller.mxml.
15:36So here, I extended it to take in the comma-delimited list of groups that a user is validated against...
15:45...and then what we do is that there's a nice gem called a list collection view.
15:57And what the list collection view allows you to do is filter a particular list based upon something...
16:05...and so we'll look at how that functions here.
16:14So every time a user comes into the system, I call this function - filterWidgetList.
16:20Every time a user logs in, I call this function - filterWidgetList - and every time a user logs out, I call this function.
16:26And it works the same way with the widgets that exist on the group as well.
16:32And so the first thing that I check for my application is if security is turned on...
16:36...because they can control security through the config file.
16:39So if security's turned on, then we get the login thing at the top of the header controller widget...
16:46...and I know that I need to validate whether or not a user has access to individual widgets or not.
16:54And then from there, I do the list collection view and pass it the widget item array collection...
17:03...and so that's already part of the header controller widget.
17:06That's how that header controller works, with the widget item array collection.
17:11So I pass my widgetItemListView, that collection, and so that's the collection that I'm working with.
17:17And now I call the filter function on that list.
17:22Okay. So and then based upon the roles that are returned, I loop through the current role that the user has access to...
17:32...and I compare that with the role that was provided in the config file.
17:38So if we look at the config file and they have all these validgroup attributes now that I added...
17:45...and so if a user is part of the BookMarksRole, then I would say, Hey, they have access to this particular widget...
17:52...and now that widget shows up.
17:54Or if they don't have access to that widget, then the widget - then the function returns false...
18:00...saying that, Don't put this as part of my list; filter this one out.
18:06And then once you - and it does that for each of the items, and then you provide your list view filterListView to the...
18:17...data group that's controlling what you see on the header widget control...header controller widget.
18:26So we can see that in action here. I'm sorry, let's see. Let's go through it a little bit.
18:42So if we look at our configuration file, I have a particular user that has access to bookmarks...
18:49...and then another role - these are roles. This role has access to bookmarks too, as well.
18:56So BookMarksRole1 and BookMarksRole2.
18:59Then I also put some permissions on the edit widget, and so whoever's part of the EditWidget role...
19:10... has access to the edit widget and then the extract data widget is somewhere in here.
19:19Extract data widget has the ExtractData role.
19:23And so you can have any combination that you want as far - as long as it's comma delimited in this particular implementation...
19:31...and they can have access to as many widgets as you need them access to or as few.
19:36And then by convention, I just have an all for all the other widgets that a particular user may have access to.
19:47So then if we look into our database and look at the users, here are a set of users...
19:58...and so I just named them so that way I knew which users had what permissions.
20:01So we have this user that has access to the bookmarks and the edit widget, this user just has access to the bookmarks...
20:09...this user #2 just has access to the bookmarks, but this one is only part of the BookMarkRole2 role...
20:19...and this one has access to the edit widget and the data extract widget.
20:28So when they first come into the application, you don't see the bookmark widget, because that would be right here.
20:39I think on this one would have the edit widget, and then on this one would have the extract data widget...
20:48...which is different than the data extract widget. So there's the extract data widget here.
20:53And then so we can log in, and once the user's authenticated, now they have access to the bookmark widget.
21:18And let's see. So this user has access to the bookmark widget as well as the edit widget...
21:27...so if I go back to the application, then I should go over here, and now I have access to the edit widget.
21:34But I still don't have access to the edit data extract.
21:39And so I could log out, and then we see that the header controller widget takes away that authentication...
21:48...and then we can proceed and log in to somebody who has edit widget and edit data widget permissions.
22:01So we'll log in, and so now we see that they still don't have permissions to the bookmark widget...
22:11...but they should be able to see the extract data widget as well as the edit widget.
22:18And so, you know, you can begin, start to do a lot of fun different things with this particular implementation.
22:23So one of the things that I did for this particular website was to control the - then I'll close it, or are we just too small. Okay.
22:43So for the table of contents. So right now, when they first log in to this website, you know...
22:48...they don't have access to a secured service.
22:52But then if they log in - if I can remember my test user. Give me a second.
23:21Now they have access to this particular layer that was previously secure.
23:27And so this provides a lot of flexibility and a lot of capability, and I've used this particular implementation against...
23:37...not only ASP.NET databases, but I've written custom membership providers...
23:41...and had to authenticate against Oracle databases as well.
23:46And so far, it's been really scalable.
23:51One of the things that I also had to do was at the widget item level, provide security there.
24:00And so, you know, a user would have to have permissions to access this particular widget item, but not this widget item.
24:08And so I was able to extend this solution and provide that level of capability as well.
24:14And so if we log out, then we should see that that particular layer was removed from the application.
24:29So, you know, when I first started out, I was kind of wary. I was just telling my project manager, you know...
24:36...I always give everything my best shot, so...
24:39I didn't know what the solution was going to end up being, but it wound up working really well.
24:43We've been able to apply it in a lot of different applications for our clients.
24:49So one thing that you want to just make sure is that you always use SSL.
24:55I know I didn't demonstrate that, but you always want to make sure you're communicating over SSL.
25:00And so, to my disclaimer, if anybody does access my code, it works on my machine.
FlexViewer Security: When Config Files Aren't Enough
Harold Bostic of URS Corporation demonstrates how clients can create their own configuration files.
- Recorded: Mar 29th, 2012
- Runtime: 25:12
- Views: 980
- Published: May 3rd, 2012
- Night Mode (Off)Automatically dim the web site while the video is playing. A few seconds after you start watching the video and stop moving your mouse, your screen will dim. You can auto save this option if you login.
- HTML5 Video (Off) Play videos using HTML5 Video instead of flash. A modern web browser is required to view videos using HTML5.
Right-click on these links to download and save this video.
- 480x270:WebM (55.2 MB)MP4 (57.3 MB)
- 960x540:WebM (146.3 MB)MP4 (155.1 MB)
If you don't have an Esri Global Login ID, please register here.