Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
In this video we add the ability to associate an added task with the currently signed in user. We also discuss the importance of storing encrypted passwords and add a password encoder to our application.
BCrypt Password Hashing
BCrypt is a hashing function that is based on the Blowfish cipher. It is designed to allow the ability to be iteratively applied a specified number of times (referred to as the cost parameter). One advantage of this hash is that, as processors get faster and servers have the ability to process more requests concurrently, the number of iterations can be increased so that a "brute-force" attack can be slowed to the point of detection before the attack is successful.
- https://en.wikipedia.org/wiki/Bcrypt
- https://en.wikipedia.org/wiki/Blowfish_(cipher)
- BCryptPasswordEncoder
Injecting User Data for Modifying Queries
If you want to inject user-specific data using the authentication object for INSERT statements, in the same way that we did for SELECT statements, you'll need to use a native query. Here is an example of a Spring Data JPA interface method that you could use:
@Modifying
@Transactional
@Query(nativeQuery = true, value = "insert into task (user_id,description,complete) values (:#{principal.id},:#{#task.description},:#{#task.complete})")
void saveForCurrentUser(@Param("task") Task task);
Git Command to Sync Your Code to the Start of this Video
git checkout -f v7
Using Github With This Course
You can complete this course entirely using code created by you on your local machine. However, if you choose to use the code I've made available to you, you have two options:
- Use the project files linked at the bottom of this page, or
- Use the Github repository I've made available (recommended)
If you choose the recommended option of using the Github repository, it can be found at
https://github.com/treehouse/todotoday
To utilize Github with this course, you can download the Github desktop client for your system or use the command line interface provided with Git.
Clone this repository to your machine using the Github desktop client, or using the following command:
git clone git@github.com:treehouse/todotoday.git
To update your local repository to match a video's starting point, you can use the git checkout
command in combination with the stage and video number. For example, to update your local repository to match the starting point of Video 4, you'd use the following:
git checkout -f v4
Notice the use of the -f option. This forces Git to override all local changes, so be aware: this will cause any changes you made to be lost.
-
0:00
Though our application doesn't allow a user to update a task,
-
0:03
other than marking it as complete.
-
0:05
We do allow users to add new tasks.
-
0:08
If we look at the controller method that handles this requests for adding.
-
0:12
And that's in task controller, we have add task right here.
-
0:16
We see that it calls upon the task services save method.
-
0:22
Let's look at the implementing class for that service.
-
0:25
So the task service impo.
-
0:29
We see that this class a save method calls upon the DAOs save method.
-
0:34
So let's open that class.
-
0:37
Now this one is simply an interface here that is one of those
-
0:42
spring data JPA repositories that's generated when we boot our application.
-
0:49
Specifically the save method is inherited from the crud repository and
-
0:54
is nice for creating new tasks with all fields populated and even updating tasks.
-
0:59
If we expose to users a way to do that.
-
1:01
The problem is that in order for this to be effective,
-
1:04
we need to have the user field populated in the task entity before saving or
-
1:09
it won't be associated with the user.
-
1:11
Let me show you two ways of saving our task.
-
1:14
Let's start by grabbing the current user in the controller.
-
1:17
So back in the controller, we'll grab the current user.
-
1:21
To do that in this add task method we'll add a principal parameter whose
-
1:25
value will be populated with the username password authentication token object.
-
1:30
Which is implemented the principal interface.
-
1:32
So principal.
-
1:37
Now, we could get the user entity in one of two ways.
-
1:41
The first way is by fetching the user name from the principal,
-
1:43
then using the user service to grab the user entity by its user name.
-
1:47
Here's how that looks.
-
1:50
Let's declare a user variable that's one
-
1:53
of ours not any number of these other ones.
-
1:57
I'll call it user, and I will use the userService
-
2:00
"FindByUsername" and
-
2:07
then Principle.GetName.
-
2:11
If you recall from a previous video, the principal object
-
2:15
will have a method named getName whose return value will be the username.
-
2:20
Now I do see that userService isn't recognized that's because I have not
-
2:24
auto wired it into this class.
-
2:27
Let's be sure to do that.
-
2:28
Auto wired.
-
2:29
private UserService userService.
-
2:33
There we go now down here it's recognized.
-
2:38
Now before we use the task service to save that task we better associate that task
-
2:43
with the currently up then a gated user which is now stored in this user object.
-
2:48
So to do that I'll do task.set User and user.
-
2:55
And now when the test service saves the task,
-
2:58
that user will have been associated with the task.
-
3:01
So everything will be associated just as it should be.
-
3:05
What we should know is that calling upon the userService, specifically its fine by
-
3:10
userName method will result in an additional hit to the database and
-
3:14
note this is not an expensive query to the database it will happen very quickly.
-
3:18
It's still another query to the database.
-
3:21
If we'd rather not hit the database again we can use our knowledge of java and
-
3:25
even run some quick test with output to see
-
3:28
that the principal parameter-- this principle parameter right here--
-
3:34
is populated with a username password authentication token object which
-
3:38
has a get principal method whose return value is going to be the object that is
-
3:43
implemented the user details interface in the typical spring security setup.
-
3:48
So it turns out that we don't need to hit the DB for
-
3:52
our user entity we already have it.
-
3:54
So how do we get it like this.
-
3:57
Let me show you I'm gonna delete what I did here And
-
4:03
will first start by casting the principle to a Username Password Authentication
-
4:10
token object, there's that cast to the principle.
-
4:16
Then we call the objects, get principal method, so all surround this whole value.
-
4:24
With parentheses and call getPrincipal.
-
4:29
And finally we cast that.
-
4:32
to our user object which has implemented the user details interface.
-
4:39
User, just like that.
-
4:43
And there it is.
-
4:43
So this is another approach and it definitely works.
-
4:46
Let's run the app to see if it does work.
-
4:49
I'm gonna open my run panel, and run that boot run task.
-
4:57
And the spring application is booting.
-
5:01
And has now started successfully let's go back here and will need to log in again.
-
5:05
I'll login as the first user that is just user
-
5:10
cool now we've discussed users and roles let's try to add a new task.
-
5:15
Discuss security Great it looks like it added well.
-
5:20
Let me log out from the user account and login to user
-
5:24
two to make sure this test doesn't also show up under user two's account cool.
-
5:30
It certainly does not so if I log out and log back in as the first user.
-
5:35
There it is still there for us.
-
5:39
As I said this is one approach though it's not the only one.
-
5:41
If you'd like to pluck the stuff out of the controller and push it all the way
-
5:46
down to the DAO just like we did with the find all method for getting a list of
-
5:49
tasks using the currently authenticated users ID, check the teacher's notes.
-
5:54
There are options for this.
-
5:57
Well since we now have a to do item on our list for
-
6:01
discussing security concerns let's do that now.
-
6:05
First a word of caution, this discussion is not meant to be exhaustive.
-
6:11
There is a plethora of security vulnerabilities that
-
6:14
need to be taken into consideration when developing a web application.
-
6:17
So please Do your research.
-
6:21
What we'll talk about here are two simple options that add
-
6:24
a nice layer of security to our application.
-
6:27
And that are quickly implemented whispering security.
-
6:30
The first item I'd like to discuss is the storage of passwords.
-
6:33
Currently we've stored passwords in the database as plain text,
-
6:38
such that if a malicious user gain access to the database,
-
6:41
whether through our application or not we'd be in trouble.
-
6:46
Let me show you here in IntelliJ.
-
6:48
We insert those passwords very clearly as plain text.
-
6:54
Even if they're not strong passwords they are stored exactly as entered.
-
7:00
Now should our database become compromised,
-
7:02
a simple query reveals plaintext usernames and plaintext passwords.
-
7:07
As a responsible developer you should take necessary steps to ensure,to
-
7:11
the greatest extent possible, that the data you depend on can't be used.
-
7:15
Maliciously.
-
7:17
Knowing that people often use the same passwords for
-
7:19
many if not all web applications, a data breach might have consequences
-
7:24
that stretch far beyond the boundaries of your application.
-
7:27
In short be responsible developers.
-
7:31
What we should be doing here is storing encrypted versions of passwords
-
7:35
where it is practically impossible to decrypt the encrypted version and
-
7:39
get back at the original password.
-
7:42
That is, it's a one way street.
-
7:44
Now I want to be clear that this isn't a workshop on encryption algorithms, so
-
7:48
you can do your own research as to which encrypted method you'd like to use and
-
7:52
how you'd like to customize it.
-
7:54
In this application we'll use what's called the b crypt hashing function.
-
7:59
Check the teacher's notes for more info on this method.
-
8:02
As spring provides an implementation called the b crypt password encoder.
-
8:06
So let's switch to our security config class and
-
8:09
set that up in our config package.
-
8:12
I will open security config.
-
8:13
Let me collapse this panel here so I have more room.
-
8:19
We'll start by creating a password in code or being in this class and I will do that.
-
8:26
I wanna do that right here.
-
8:30
Not all that matters.
-
8:33
So I'll say public password encoder,
-
8:38
I'll call it password encoder and I will return a new
-
8:45
BCrypt password encoder and we will use strength 10.
-
8:50
Again check the teachers notes and
-
8:53
do your own research as to what this exactly means.
-
8:57
So then back up in this method, in configuring the authentication
-
9:02
manager builder, we'll set the password encoder as follows.
-
9:07
So right after we set the user details service,
-
9:10
we will set the password encoder to what the password encoder being.
-
9:17
Now what will happen is that every time authentication takes place.
-
9:20
The submitted password will being coded.
-
9:22
And the encoded version will be checked against the database
-
9:25
instead of the plain password being checked.
-
9:27
Of course, this means that passwords will have to have been stored into
-
9:31
the database as in coded or hashed passwords.
-
9:34
So we'll need to alter our import.SQL file, we'll need
-
9:39
to replace these values with their hashed versions or their encrypted versions.
-
9:45
Now to get a hash for these passwords, you can hit up any number of online sources.
-
9:49
So let me just switch to Chrome.
-
9:52
And, and I will, in a new tab, Google, bcrypt.
-
9:58
Hash generator.
-
10:02
And I will choose will say this one right here.
-
10:07
Cool.
-
10:07
Enter the String to be encrypt.
-
10:09
So I will be encrypt password.
-
10:13
And there's the hash right there.
-
10:15
So what I wanna do is copy this entire String.
-
10:20
Just like that.
-
10:21
And I want to paste it in place of my plain text passwords here.
-
10:25
Just like this.
-
10:28
Now, whenever I include hash passwords for
-
10:31
initial data, I'm always careful to leave a comment about the plain text passwords
-
10:35
that developers will need to use to log in to the application.
-
10:38
Because he can't enter the hash in the password field of the web app.
-
10:42
So this is just a note to developers.
-
10:44
Passwords are both password.
-
10:50
There's no way for a developer to know otherwise
-
10:54
that this is actually the encrypted version of the password.
-
11:00
Password, so I leave a comment there for development purposes.
-
11:05
Now let's run the application and
-
11:07
make sure it works with our encrypted passwords.
-
11:09
So let me pop this open again I'll stop our previous instance and
-
11:12
I will rerun that boot run task.
-
11:17
Looks like everything compiled correctly.
-
11:21
And after just a couple moments, the application has started successfully.
-
11:25
So, back in our application, let's refresh and
-
11:28
let's make sure that you are using the username and password.
-
11:32
That is the hashed password on the database side,
-
11:35
will still allow me to successfully login and looks like it worked.
-
11:40
So the advantage is that now we don't have users password stored plainly anywhere.
-
11:45
And if a malicious user got ahold of our user table, we can have more confidence
-
11:49
that passwords won't be decrypted, but we can never be absolutely certain,
-
11:54
but this increased level of security is critical.
-
11:58
Alright as a final exercise, let's add CSRF protection to our app.
-
12:04
CSRF or commonly said, Caesar, stands for Cross Site Request Forgery, and it happens
-
12:10
when your application gets a request from a user that the application trusts.
-
12:14
Which is to say in our application the app receives a request from a user's browsing
-
12:18
session which would pass along the jsessionid cookie.
-
12:22
Thereby granting the request whatever authentication privileges are associated
-
12:26
with that jsessionid.
-
12:28
So how can we protect against the damaging affects of this.
-
12:32
Now the first approach is to stop using get requests for
-
12:35
anything that changes server's state.
-
12:37
One can certainly code an application that can change database data or
-
12:41
other server resources from a get request.
-
12:43
But this goes against HTTP specifications.
-
12:46
And though those specs aren't enforced, they are there for a reason.
-
12:50
As for those post requests, which do change server data,
-
12:54
we can add C.S.R.F. or csrf protection to our app.
-
12:58
Let me show you how you can turn this on for spring,
-
13:00
and then I'll show you the effect it has.
-
13:02
So, to add this protection, we'll open our security config class.
-
13:07
Collapse this again.
-
13:09
Let's scroll down to our security filter chain right here and
-
13:14
after the log out configuration we'll continue the chain by adding
-
13:18
and followed by c serve.
-
13:24
There it is right there.
-
13:28
And that's all that's needed to add cserve of protection into our application.
-
13:33
So let's fire this up and see what effect this has had.
-
13:36
I will stop the previous instance and rerun.
-
13:40
Compiled successfully.
-
13:46
And booted successfully, so let's refresh this.
-
13:51
Now we see the same login form that we've been seeing all along.
-
13:54
But it is actually different.
-
13:57
Let's inspect the form and see what has Changed.
-
14:02
If you look at the generated markup you'll see a hidden input right here.
-
14:07
With the name_cerf and its randomly generated value.
-
14:13
On the server this value will be saved in session data and
-
14:17
will be compared to the value that's passed with the form submission.
-
14:20
If the value in the submission is different from the server side session
-
14:24
data, the request will be rejected.
-
14:27
And since it would be highly unlikely that another website open in the same
-
14:31
browsing session, would somehow come up with this value,
-
14:34
this serves as a nice protection against these sea-surf attacks.
You need to sign up for Treehouse in order to download course files.
Sign up