Spring Boot + Spring Security with JPA authentication and MySQL from scratch - Java Brains

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let's set up a brand-new spring boot project from scratch with spring security that works with database authentication using JPA in connecting to a my sequel database I'll walk you step-by-step through how to get spring security to connect to the my sequel instance using JPA and authenticate users against the user information stored in that database [Music] the primary objective of this tutorial is to have a spring security application connect to a database or my sequel database using JP and get user information from there so that when somebody's trying to authenticate it's gonna check if that user is available in the database and check if the credentials are correct all right so I have this my sequel instance locally that I can sign into with the my sequel CLI and I have a database instance called spring security all right and in this database I have a table called user I can do a select star from user and here you see there is a single user available in the system alright so this is a user table that I've created with a bunch of columns there is a column called user name there is a column called password which obviously as you can tell stores to username in the password there is an active column which indicates of the user is active online I have one record in this table which has the username as user password Espace and activist it to true there's also a roles column which I intend to be a comma separated list of roles that a particular user has this is usually not the case in a real world application you would typically have like a separate table for roles and authorities and all that stuff and have like a foreign key reference but for the sake of this video I want to make things simple so I've just added this comma separated list of roles in the roles column for this one user that I've seeded into this table I just have one role which is role on the score user right so this is the single user we have in our system what we want to do is create a spring boot project from scratch at Spring Security in there and have spring security connect to this table and this database in this sequel my sequel instance using JPA so that when I log in with the username is user and the password is past it should have come query this table get this record and then validate it and say ok this is a good user and then I should be able to successfully authenticate this is the objective of this tutorial alright so let's see how to do this I'm going to start by creating a new spring boot project from the scratch using standard spring that IO and will enter my group name as I order Java prints and my artifact name as spring security JPA all right so this is my spring security JPA project and now I need to add a bunch of dependencies here there are a couple of obvious dependencies that we need to add since it's a web application I need to add spring web starter and obviously need spring security starter and since this is going to be using GPA I'm gonna add the JPA dependency as well now when you're connecting to a database you need to install the driver for the database you're connecting to in this case I'm using my sequel so I'm going to choose the my sequel driver I'm gonna add that here as well and now I can generate the project and open this in IntelliJ now here's my project open in IntelliJ I'm gonna switch to the packages view here and the first thing I'm gonna do is create a resource class all right so I need to create a couple of api's that can be accessed in order to verify if the authentication is working fine all right so I'm gonna make this rest controller and I have essentially three api's the first API is mapped to the root URL slash and this I intend to be accessible to everybody where there are people have logged in or not I want this to be publicly accessible and I have a slash user API which I want to hide behind an authentication wall right I want people to be able to authenticate before they access it but then once you've authenticated respective whether you have a user role or an admin role you should be able to access this slash user API and then I'm a slash admin API which I want to be accessible only by somebody who has an admin role so someone has to authenticate first and they need to have an admin role to be able to access this all right so now I need to set up the authentication and the authorization part of it right spring security is already a part of the classpath because we've added it as a dependency but now how do you configure spring security you do that by creating a class that extends that security configure our adapter so but in a new Java class and I'm going to call this security configuration right and this is going to extend the pub security configured our laughter if you're not sure what this is you need to check out this tutorial that's showing up in the card here but I talked about all this in detail oh and once I extend this class I can create a couple of methods here which lets me access some core spring security objects and using those objects I can tell spring security what to do all right so the first method that I'm going to alright is this configure method which takes in the authentication manager builder as you can imagine I can use this authentication manager builder to configure authentication and here I need to tell spring security to say hey this is this authentication needs to be through connecting to JPA and getting the data from the database using my sequel all that stuff I'm going to not do this for now let me set up the authorization first and then we'll get back to authentication authorization is by using another configure override and this time I'm using the configure which takes an HTTP security and here I'm going to paste this block of code which sets up the authorization for different API so we have three api's I need to set up authorization for all three right so what this is doing is the first line says authorize I'll request the slime says okay for the slash admin API allow only if the user has the role admin all right and this one says for this slash user API allow if the user has either admin or the user role and then the slash API which is the root just permit everybody and then this last line says Allah form login all right so now we have the authorization set up it's time to set up the authentication now how do you set up our dedication for spring security to connect using JPA to my sequel so there are a bunch of out-of-the-box implementations for authentication that spring security provides for example if you want to use JDBC authentication there is a JDBC authentication manager that you can use and tell what the database is what the query is and all that stuff if you're curious to learn about that check out this card which talks about how to connect to a database using DBC in our dot indicate if you want to use LDAP there is an LDAP provider out of the box and you can configure it to do what you wanted to do however for a GPA there is no out-of-the-box implementation for authentication so the v2 have spring security get data from the database using JPA actually has got nothing to do with GPA at all so think of this picture about how authentication works so you have the authentication manager which talks to authentication providers which talk to the user details service right so the user details service has one method which gets the user information based on the username now spring security has a way for you to provide this user detail service and you can say hey I'm gonna create this user details service and give it to you and this service that I'm gonna create is going to take in a username and then it's gonna return you a user object the user object is of type user details all right so you can create the service and hand it to spring security and say any time you need to look up a user call my service and now spring security is going to manage the rest all right here just gonna show you the login form it's gonna get the user information the user ID and the password and then when it needs to validate the user ID and password it's gonna call your service and say hey service somebody's trying to authenticate with this username get me the user details for this guy alright and now your user details service can return the user details instance for that given username and spring security is gonna trust your service and say ok so this is the user that's in the system I'm going to validate against that user so you have the ability to create the service which given a username returns user information in order to have spring security work with JP what you need to do is to create an instance of this user details service once you create an instance of this user detail service the logic that it does the functionality that it does is basically lookup the user using JPA alright so this is the reason why I say that this particular think that you need to create is not dependent on JPA at all you could have the service look up users from a text file you could have the service return hard-coded users it really doesn't matter it just so happens that the way to get spring security to work with JPA there's no out-of-the-box implementation you have to create this user details service instance in order to have it to work alright so in order to prove this what I'm going to do is create this user details service which returns a hard-coded user first just in order tell you that it has nothing to do with JPA specifically alright so what I'm gonna do is I'm gonna use this method on earth called user details service and this lets me pass in a user detail service instance alright so I can create an implementation of the user detail service interface and make that as a spring service right annotated with a spring service and then set it on the authentication manager builder object and now the just with this spring security is gonna call the method on this user detailed service to get user information every time there is an authentication attempt right so this obviously doesn't exist right now so what I'm gonna do is I'm going to create that service and then auto wire it to a member variable over here and I'm going to create a user details service member variable I can once I create an implementation of this thing which has a stereotyped annotation like a service or whatever spring is gonna fire it in and then that's gonna go to the authentication manager builder and the authentication manager builder is gonna call this user detail service in order to look up a user now how do you create an implementation off this user details service well let's actually do that now I'm gonna create a new Java class and I'm going to call this my user detailed service and this of course has to implement the user details service the capital you here and now there is one method that I have to implement which is load user by user name right so if I were to implement this but some logic right it doesn't even have to do with GPA implement some logic which returns the user details instance for a given user name that's all it takes spring security is happy with it it's gonna call the service every time somebody is trying authenticate it's gonna pass in the user ID and it's gonna trust whatever this services are taught right whatever user details instance it returns the spring security framework is gonna trust it and it's gonna authenticate against it all right so I'm going to create a hard-coded user details instance over here all right so let's say I create a new java class which is going to be an implementation of this user details interface alright so this is going to implement user details now there are a bunch of methods that I'll have to implement obviously see this they're a bunch of methods here it has the username it has the password it has the authorities and it also has information about whether the account is expired the user is enabled or not and all these things right spring security is going to take this value that the user details service returns and this is what it's going to use for authentication all right so I'm going to implement this I'm just going to create a bunch of hard-coded values here so let's start with the get get authorities right this is the first method the get authorities method returns a collection of granted authority instances right so what I need to do here is if I'm hard coding it I need to return a list of granted authorities right so but so pause that and trying to implement the other stuff and we'll get back to that later right so let's take a look at some of these other methods starting with user name I'm going to create a member variable called user name and I'm gonna create a constructor which takes in the user name as an argument and then I'm going to set this user name onto the spender variable right so basically what I want to do is have the user detailed service return an instance of this user details object depending on whatever the user name is the user name could be foo and I'm just going to return a user details object with the name s foo the hard-coded password alright so I don't wanna hard code the user name here I just want to take whatever is passed in so that's the reason why I'm doing this everything else I'm going to hard-code alright so now that I have taken the user name as an argument and in the constructor and I'm accepting this let me actually create an MD constructor here as well now I returned that username implicit username method and then in the password get password method I'm just gonna hard code the password is pass and everything else I'm gonna head quarters well there's a countin on expired true the account hasn't expired is the account unlocked true the credentials not expired true and then as user enabled true so hard-coded everything here except for the username which I'm just passing and mirroring whatever spring security is gonna pass to me all right and then finally the authorities I need to return a list of granted authorities so I'm going to do a raised as list and I'm going to create a simple granted Authority which is basically an implementation is one instance of granted Authority and I'm creating role user so again even Authority I'm hard-coding to be of one role which is role underscore user now we have a hard-coded my user details now my user details service is going to return an instance of this my user details right so whatever the user name is passed in I'm just gonna create that user details object out of it so that it has the same user name as what's passed in but everything else is hard-coded alright so I am just going to return this and everything else here is pretty much hard-coded with the password pass all fields are enabled and this is what's going to get returned by my user details service now in order to have the service work and have spring security detected and autopilot I need to of course create this service annotation which is a stereotyped annotation and this lets bring security know that this service exists and it auto wires into my security configuration class and finally in my security configuration I need to create this at enable web security annotation to tell spring security that this is a configuration class and the final step the final final step is to create a password encoder here the case spring security expects you to have a password encoder right so I'm just using the no op password encoder in order to get this to work basically I'm telling spring security hey I'm just using clear text passwords no encoding required of course this is obviously not going to be useful in production you don't want to be using this in production but for tests this is fine so essentially what we've done here so far is configured spring security to depend on a user service user detailed service and we have a user detailed service pretty much returned a hard-coded user details object whatever user name is passed in it just creates user details object with that user name and everything else hard-coded all right so now I can actually run this application believe it or not right so again this has got nothing to do with JP we haven't used JP a yet I have basically leveraged the spring securities user detailed service hook in order to create a custom user detailed service now I can go to slash user and I would obviously expect me to enter my username and password what's the user name and password I enter well I can actually use anything for the username password has to be passed because that's what's hard coded but I can enter gibberish for the username here password pass sign in and I'm in so what's happening here is spring security is calling our user details service and saying hey do you have a user with this particular gibberish name give me the user details and then what my user details service is gonna do is it's gonna return this my user details instance and it's gonna pass in the username that spring security is passing for us it's basically whatever the user is trying to authenticate right it's gonna take that username and it's gonna pass it to this method and then we are returning an object with roll user with the password has pass and with the hard-coded username and spring security is gonna go okay looks like there is a user in the system with this particular username and with the password has passed it's gonna compare the password ok everything is good as from a letter saying alright so this is how you use user details service to connect to some other source of user information this could be JPA this could be anything else you can easily imagine this load user by user name method connecting to some source of user information retrieving the user given user name and then creating this user details object and handing it back to spring security now we can imagine what it takes to get this to work with JPA oh this load user by user name method needs to call a JPA api to get the user information given a user ID that's as simple as that right so everything that we're gonna be doing from now on is basically just GPA stuff it's not even spring security stuff we've got the spring security wiring in done already all right so all we need to do is setup JPA in our application and set up a repository class and an entity class and then have a method which looks up a user from this is from the database given a user name once you have that method there all you need to do is take this out no hard-coded users anymore instead call that GPA method all right that repository method that you would have written once you do that you can create that user details object to my user details object out of the return of that JPA api all right that's all you need to do here so now the rest of this tutorial is going to be only about setting up GPA so let's see what it takes to set up JPA the first thing I'm gonna do is to create that entity class I need to create a user into the class so I'm gonna do that and then let me put this in the models package write the entity class is JPS way of saying this is a class that's backing a certain table so you can have a row in a table represented by an instance of this class as object relational mapping alright so this is my user instance now I'm also going to move this user details or class to the models package that makes sense for those two to be there because they're both technically models alright so now what do I create in my user class the first thing I need to do is to mark it as an entity using the add entity annotation and then I can also specify and at table and then specify a table name all right if the table name is different from user you can specify it here using something like this I can say name equals then you can give it the name you want your happens to be user in which case you actually don't need to add this at table annotation it's basically the name as the same name as a class and JP automatically maps it to that name all right so now I'm going to create a couple of fields over here and let's say let's start with an ID all right so we need an ID I'm going to create an integer field ID with the ad ID annotation I'm also going to use a generated value to have JP a generate an ID automatically the strategy is generation type Auto which basically says hey JP a figure out the ID and I want to be bothered with this when I'm inserting I'm just inserting the other field right JP is going to take care of the ID and now the fields that we are interested in we are interested in the username we are interested in the password we are interested in an active field I'm gonna create a boolean called active and I'm gonna be creating a string rolls alright so this rolls is all these fields are going to correspond to the four columns that you saw in my sequel in the beginning of this tutorial right so each column here each column in the database corresponds to each field in this class the names here happen to match exactly so I don't need to add extra annotations but you can provide more hints to JPA if your field name is different from the column name in your database all right now I need to create a bunch of getters and setters so I'm gonna create getters and setters for all of them and that's it I am done with the entity next thing I'm gonna do is create a repository so I'm going to go here create a new class and I'm going to create that repository call this user repository there's actually an interface let me change this to an interface I need to create an interface which extends the JPA repository and then I specify the types your user and the integer I'm actually blazing through the GPS stuff here because the focus of this tutorial is not really JP at Spring Security but a brief introduction about repository it's basically an interface which has implementation that comes out of the box with JPA all you need to do is provide the definition of your method right so you're not creating the implementation here you're creating a definition of the method and then Gopa provides the implementation automatically so here you are saying hey JP a I need a method which finds by username right and I'm gonna create fine by using a method which takes in a string as an argument and what this does is it tells Spring JPA that this particular service there needs to be an implementation which needs to work on the user entity as you can tell from the generic type in JP repository so this is this deals with users and then the method provides a hint about what this needs to do right it says ok given I user named JP a needs to create a method implementation which finds a given user so there are two clues that we're providing to JP a to implement this method the first clue is that this is of user type as you can infer from the generic type and the JP repository if the second clue we are telling GP is I need a method which finds this user type given a user name right so that's the find I user name method and then it takes in user name as an argument so there are method names the type names all these things provide hints to JPA about what to do alright so this is you specifying your intention is you're saying I need this functionality to look up a user given a user name and JP is gonna create the implementation for you so that you can call this method without having to implement it yourself you just write the interface and the implementation is provided for you based on what you want alright so now that I have this interface I can actually call this method to get the user information right so I'm going to to get an instance of this repository in my user details service right so now what i'm doing here is replacing that hard-coded user details with a call to the user repository right so i'm going to create a member variable here and then I'm gonna add Auto wire right so that spring is going to get an inject that instance of user repository into my user detailed service know that I have this I can replace this line with a call to use a repository may actually change this to username I'm getting the username here right so I'm gonna say user repository dot fine by user name and I'm going to pass in the user name now when somebody does authentication spring security is gonna call the service it's gonna call the load user by user name and pass in the user name and now what we're doing is we are passing that user name to the user repository and say hey user repository give me a user that has this user name now user repository is gonna give us a user write this is an optional so call this user and now when I get this user I need to convert this to a type my user details alright so I need to create a my user details instance again but instead of what we did last time which was hard coding the details I'm going to populate the values in that instance with the value that you get from the see user instance over here alright so let's say return new my user details I need to somehow get that user information from whatever the repository returns and I need to convert it into an instance of my user details let me actually create this constructor and I my user details class which takes in a user instance and then maps it to its own fields alright so instead of a string this time I'm going to create a user argument in the constructor and now I'm going to take each individual field from the user and map it to a corresponding field in the my user details not hard coding everything anymore so I need to hold the values in this class so I'm going to create member variables for all those values right I'm gonna clear I already had a user name property I'm going to create a password a boolean active and then I'm going to create a member variable which is a list of granted authorities right now I cannot create a single Authority anymore I need to get the rules from the database and then map it to a list of granted Authority so that's going to be my member variable here so we need to get a list of these guys here right so I'm going to set that as a type list of granted Authority thirty's all right and now in my constructor I need to extract those values from the user instance that we've gotten from the repository in converting into the user details instance which is what the user details service is gonna return to spring security all right so now I'm going to map those fields here let's say the start username is basically whatever is username in that input object that we get from the repository password again I'm copying it over the StarTAC is again from whatever we get back and then this start authorities so this one's gonna be a little trickier I cannot just copy the rules alright so what I'm gonna get back here with the rolls at least with the way I've implemented it is a comma separated strings set of strings alright so what I need to do is split that based on the comma and then what I need to do is call that new simple granted authority for each of those things right so do you see what I'm doing over here with the hard-coded roll user right so I'm creating a new simple granted authority for a given string I need to do that but for each of these values that I have managed to split from the input rolls right in the comma separated list I need to convert each of those values into a simple granted authority so what I'm gonna do is I'm gonna get a stream out of this I'm gonna do arrays dot stream and for each of these values I'm going to map it to the constructor I just basically need to pass the value to the simple granted authorities constructors and I'm just gonna do a simple granted Authority and then the new function there and then once that's done I'm gonna collect everything and then that's going to be my authorities member variable right so what we're doing here essentially is converting that user instance that we get from the database into this user details object we are not correlated earlier now we are populating it with live values that's reason why we took that from the constructor all right so now that I've done this I can essentially remove the other methods that I have over here and basically just implement the methods that the user details interface needs all right so all these methods just need them to learn this stuff and referring them off of the member variables gate authorities is just gonna get returned the authorities member variable that you have said in a constructor forget password the password member variable user name is gonna return the username and the variable there's a count non-experimental it's hard code this one right they don't want to track all those fields is that gonna unlock to still true is correct it's not expired is still true is enabled I can probably use the active flag for this so this part we are not coding all right so now we have the my user details instance which is getting the values from live data right whatever user instance you pass in it's gonna critic it's gonna construct the my user details instance dynamically now let's go back to the user details service and now what I need to do is take the user object out of this optional and then pass that user object to that constructor of my user details and whatever is the result in instance that's what I'm going to be returning all right so I'm gonna do a map from this optional and then I just need to pass that value to the my user details constructor new function and then I'm going to get the value and then this is what I'm gonna return right so with this I have gotten the user instance from the database from the repository convert it into a my user details instance and I'm returning this but of course this is optional so this may not have a value right let's say somebody's trying to access some user name like that rubbish username that I entered earlier that's obviously not going to be there in the database and the repository is going to return is not going to return a value in which case what do you have to do well the clue is over here you have this exception that this method needs to throw which is a user name not found exception so that's what we need to do over here so what I'm going to do is I'm going to check if the user exists if not I'm going to throw that exception user dot use this are else throw method which is basically checking if an optional has a value if it's not then it's gonna throw an exception right so I'm going to pass in this lambda which is going to return a new exception for it to throw it's going to put a message here it is not found and the user name that we were not able to find all right with this we have the load user by user name complete and getting the value that it's so spring security is going to call this method passing in the user name and this one's gonna pass it to the repository get the value from the repository convert it into a user details instance and then send it back all right one final step that's left is to go to this JPA application class which is the class with the main method and enable JPA alright so the way to do this is by using the add enable JPA repositories right so this does class bot scan and what I can pass over here is the package name or the class name where the repositories lie right so this is what allows the JPA framework to look at those repositories and create those implementations environ all the functionality and all that stuff right so this is essential when you are working with JPA now the next question is you have configured JP you know how does it know where the database lies you need to configure the data source spring JP and needs to know where the data base is what the data base is right so I'm gonna go to my application or properties file and I'm gonna set a bunch of properties here first is the database URL the data source URL rather and I'm here I'm pointing to the my sequel URL that is running on localhost and the database is spring security that we just saw and then the next property then in asset is the username which is root and the password for this instance happens to be just password and this when I into that I had a couple of hibernate properties here one is the the hibernate DDL Auto is update which is basically saying don't just restart the whole database creation process every time just use the existing database there don't just wipe it off and create it from scratch that's what update does and then I have the naming strategy which is the improved naming strategy and the my sequel dialect and I want to get into all the details off those properties but basically their standard GPA stuff all right so now I can start my application guess what our application is all set and ready to connect to the JPA instance all right so now I'm going to enter the actual user username this user and the password is passed and I'm gonna hit sign in it's going to spring securities again going to refer to the user details service which we have and now you see detailed service is gonna not just bluff and give some hard-coded user back it's gonna get that single user we have in the database and spring security is gonna verify against that and there you go we were able to connect to that database and return the value so this was a complete look at how we can create a spring boot application that spring security connecting to JPA from the scratch and like we've learned in this tutorial the part about spring security connecting and getting the user information has got nothing to do with JPA at all it's just about creating that implementation of the user details service and in this particular case the user details service happen to use JPA in order to retrieve the records there is one other out-of-the-box implementation that spring security provides for looking up users which is LDAP we talked about how spring security has out-of-the-box features for JDBC and LDAP JPA doesn't happen to be one of those things which is why we had to do the user details service implementation but for LDAP you don't have to do this you can just leverage the existing support all you need to do is configure what that LDAP instance is so we learn how to create a new spring boot project from the scratch which connects to LDAP and authenticates against in this next tutorial [Music]
Info
Channel: Java Brains
Views: 400,775
Rating: undefined out of 5
Keywords: java, java brains, tutorial, brains, koushik, kaushik, brainbytes, explained, java tutorial, learn java, java tutorial for beginners, java programming tutorial, java programming, java programming for beginners, spring, spring security, programming, spring boot, koushik kothagal, beginner, java training, authorization, authentication, spring boot microservices, jpa, mysql, userdetailsservice, jpa repository, entity, spring framework, spring boot security, spring security tutorial
Id: TNt3GHuayXs
Channel Id: undefined
Length: 37min 45sec (2265 seconds)
Published: Fri Sep 13 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.