This workshop will be retired on May 1, 2025.
Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Time to add a security layer. It has been requested that all API requests are authenticated.
Fellow Students
List<User> students = Arrays.asList(
new User("jacobproffer", "Jacob", "Proffer", "password", new String[] {"ROLE_USER"}),
new User("mlnorman", "Mike", "Norman", "password", new String[] {"ROLE_USER"}),
new User("k_freemansmith", "Karen", "Freeman-Smith", "password", new String[] {"ROLE_USER"}),
new User("seth_lk", "Seth", "Kroger", "password", new String[] {"ROLE_USER"}),
new User("mrstreetgrid", "Java", "Vince", "password", new String[] {"ROLE_USER"}),
new User("anthonymikhail", "Tony", "Mikhail", "password", new String[] {"ROLE_USER"}),
new User("boog690", "AJ", "Teacher", "password", new String[] {"ROLE_USER"}),
new User("faelor", "Erik", "Faelor Shafer", "password", new String[] {"ROLE_USER"}),
new User("christophernowack", "Christopher", "Nowack", "password", new String[] {"ROLE_USER"}),
new User("calebkleveter", "Caleb", "Kleveter", "password", new String[] {"ROLE_USER"}),
new User("richdonellan", "Rich", "Donnellan", "password", new String[] {"ROLE_USER"}),
new User("albertqerimi", "Albert", "Qerimi", "password", new String[] {"ROLE_USER"})
);
Gradle
compile "org.springframework.boot:spring-boot-starter-security"
Learn More
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
Okay.
So we had quite a nice dog and pony show
0:00
building out our web facing repository
that communicates using hyper media.
0:03
I'd like to show off now how we can add
a layer of security on top of our API and
0:07
make sure that we restrict
access to the right people.
0:11
Our product manager Hannah
has requested that all users
0:15
of our API are authenticated.
0:18
And remember that means
how we identify our users.
0:20
Over the next few videos we'll build
out some basic security just so
0:23
that you can get the gist of things.
0:27
So let's do this, let's store who
created each review using our API and
0:29
we'll further make sure that
only administrators and
0:33
the actual reviewer can delete reviews.
0:36
That's right, right now anyone can delete
any review in any course for that matter.
0:38
Yikes, we better put some protection
in place, but first we need users.
0:43
Well, let's do that.
0:46
All right, so we're gonna lean
pretty heavy on spring security.
0:48
Now, if you're looking for
0:51
more information on spring security,
there's a workshop for that.
0:52
Check the Teacher's Notes.
0:55
So let's add spring security
to our gradle build file.
0:56
And what we want in here is compile
'org.springframework.boot:spring-boot-sta-
1:03
rter-security'.
1:12
All right, so now we need to add a new
feature to our app and that's users.
1:18
So, what should we do?
1:23
That's right, create a new package.
1:25
Let's add our newest feature, users.
1:26
So it's gonna be user.User.
1:32
We're gonna mark this as an @Entity.
1:37
We're going to have it
extend our BaseEntity and
1:41
we're gonna wanna have a first name and
a last name.
1:46
So, We'll dupe that line,
and make this last.
1:52
And we're gonna be using this to login,
so we're also gonna need a username.
2:00
So we'll do, private String username,
and since we're gonna use for
2:04
authentication, let's
add a password field.
2:11
Now, remember, we have this
exposed on the web at the moment.
2:20
And whoa, does this make me feel nervous.
2:24
So, let's do this.
2:26
Let's make sure that no matter what,
this will never ever be shown,
2:26
never ever exported,
we're gonna put a @JsonIgnore on there.
2:31
So we feel pretty good about that but
2:36
how do you feel about storing
that password in a string.
2:38
I mean if somebody gets a hold of
the object they could just get a hold of
2:40
the password.
2:43
I don't feel very good about that.
2:44
Sometimes people use the same
password across multiple services and
2:45
that's just not good to
have the password exposed.
2:48
So, I was thinking maybe we could just
store an encrypted version of it.
2:51
Now, again, Springs Security has her back.
2:55
So a common approach is to expose
a password encryptor on your
2:57
entity as a constant.
3:01
So let's do that.
3:02
So let's make a private or,
no, actually, I'm sorry.
3:03
Let's make a public, so
you know that people to use this,
3:06
static final PasswordEncoder.
3:11
Cool, we need to refresh our Gradle also,
3:18
in those that we're talking about,
don't we?
3:19
So used to having that on auto that,
all right, so
3:23
now it should know what
we're talking about.
3:27
That's it.
3:29
That is not it.
3:31
And PasswordEncoder and
we can choose that, here we go.
3:32
And for now, let's just make that
a new BCryptPasswordEncoder.
3:36
More on the teacher's notes if you want.
3:42
All right, so let's go ahead and
we'll make a Setter for
3:44
that password field that just
goes ahead and uses an encryptor.
3:49
So you pass in the string Password and
we're gonna go ahead and encode it.
3:54
Okay, no matter what is set for
4:00
that password encoder,
this is kind of a common practice.
4:02
Phoo, I feel a lot better, okay and
we're also going to do a little
4:06
authorization like what
the user is allowed to do.
4:10
So, we'll do that using
a role-based system.
4:14
So, let's just add some simple
strings that will represent our roles.
4:17
Now, they probably don't ever
wanna show those either.
4:20
So let's do this,
let's make a new @JsonIgnore field and
4:23
we'll say private,
just use a string array, right?
4:28
We can do that, we'll say, roles.
4:33
Okay, let's go ahead and we can
generate all the getters and setters.
4:34
And we definitely don't wanna push
those other to, we can do the, well,
4:42
password that we pass out will
be encrypted, so that's okay.
4:47
So we're gonna pass all that stuff up,
here we go.
4:51
And again,
it's not gonna come out across the web but
4:57
if you have access to the user object
which should be something that we trust,
4:59
Tthey'll have access to
get hold of these things.
5:03
Once we generate a new constructor
that basically takes everything.
5:06
And then in the constructor instead
of setting the password this way,
5:09
let's call this password,
let's just call set password.
5:14
And we'll set it with
the password that came in, right,
5:19
the password that we passed will be
plain text, then we'll do that across.
5:22
And remember it's an entity so
we need to make a protected User and
5:28
it calls super, and then we need to make
sure that this calls that, all right.
5:34
This we're gonna call our protected
user for whatever set up is that.
5:39
Awesome.
5:43
Okay, that's feeling pretty good.
5:44
Let's go ahead and make our repository.
5:45
So we'll make a new Java Class and
we'll set it to an interface and
5:48
what we're gonna do here is it
will be called the UserRepository.
5:53
And it is going to extend
5:59
the CrudRepository and
6:04
that is of type User, and the ID is Long.
6:10
Okay, so here's the thing.
6:20
If we don't do anything,
6:21
our API is going to export this repository
just like it did for courses in reviews.
6:22
And we don't want someone just
browsing our users, do we?
6:28
It seems like pretty bad form.
6:30
So, what we want to do is we want to use
spring data because it's awesome, right?
6:32
It's gonna generate all the querying but
we don't want to have it restified, right?
6:37
So, why don't we just use this annotation.
6:42
So we're gonna do this,
we're gonna say @RepositoryRestResource,
6:44
and we gonna pass exported = false.
6:51
Now this doesn't exist,
there is no slash users off our API.
6:55
Now, we're gonna be having the user
enter their username and password.
7:01
So in order to get spring
security wired up correctly,
7:03
let's expose a finding by username method,
right?
7:07
So that will return a user and
it will be fined by username and
7:10
again because of that naming thing,
it's just gonna work.
7:16
We're gonna say (String username),
awesome.
7:18
That will come in handy in a bit.
7:21
Okay and now finally let's add
the relationship between the review and
7:23
the user, okay?
7:27
So let's go to the review and
right here, it's a many to one, right?
7:28
One user can have many reviews.
7:35
So let's say private User reviewer.
7:38
And let's go ahead and come down here and
we'll generate the getter for that so
7:44
that we can use it if we want to.
7:48
Let's do the getter and the setter.
7:53
Okay, this is feeling good.
7:57
What do you say we generate some
users in our database loader?
7:58
Okay, so
let's go over to our database loader and
8:01
now we can set proper reviewers for
each one of these.
8:05
So let's add a list of users
that will call students and
8:08
we'll add them using that
arrays as a list static method.
8:11
Now, I sent out a call to the Twitters and
8:15
I added them to the teacher's
notes here for inclusion.
8:17
So, go ahead, go down to the teachers
notes and grab the students who were so
8:20
nice to let us share their name for
test data.
8:24
Thank you everybody for
helping our tester application.
8:26
So I'm gonna paste that here.
8:31
Let's make sure that it knows
what we're talking about, okay?
8:32
And we also need to import our user
repository that we just created,
8:36
so we're gonna say, final UserRepository,
and we'll call that users.
8:41
Of course, it's gonna complain.
8:47
And what we'll do is we'll add
it as a constructor parameter.
8:49
There we go.
8:55
So, now we can go ahead and
8:58
call users.save(students).
9:02
Awesome.
9:07
So now all those users
are in our database,
9:09
I'm gonna actually add myself too.
9:10
So let's say, users.save(new
9:12
User("craigsdennis", "Craig",
9:16
" Dennis" and my password that I'm gonna
use, the same one I use for my luggage.
9:22
"12345" and we'll do a new String.
9:28
And I'm gonna give myself, not only
am I gonna give myself the user role,
9:33
I'm also gonna give myself
the admin role now.
9:39
I just made that word out.
9:41
We haven't done anything defining
what admin actually means, yet.
9:42
You can call it whatever you want.
9:46
I just wanna create a role that
can do anything, basically.
9:47
So, eventually we'll make it, so anybody
who has admin can do whatever they want,
9:51
but for right now this is just a word.
9:54
Okay, so let's do this.
9:57
Let's extract this review.
9:59
Let's do a Refactor > Extract > Variable.
10:02
What's the reason that didn't work?
10:12
I have the wrong amount
of stuffs selected there.
10:15
There we go.
10:18
We gonna choose Refactor
> Extract > Variable,
10:20
here we go and
we're gonna call that the review there.
10:25
And so what we need to add is we need
to now that we have this review,
10:31
going to say review, setReviewer.
10:38
And we're gonna use the same trick.
10:42
We're going to say students.get, and
10:43
index is going to be (i % students.size),
10:48
a little module math there.
10:53
And you know what I noticed right
here when I pasted this out?
10:56
This actually needs to be, this could
return 0 which is not what we want.
10:59
So we want, there we go, instead of
being 0 to 4, we want to be 1 to 5.
11:04
Modulo math, this is probably too
many parentheses, don't do that.
11:11
When we added the dependency
to spring security,
11:15
spring boot does what it does best.
11:18
It automatically configured
our API to be secure.
11:19
Now, the problem with that is that we have
no way for the users to currently log in.
11:21
So, let's take a quick break and swing
back and configure spring security to use
11:26
our new user entity for
both authentication and authorization.
11:31
Now is a probably a good time
to go take a quick stroll,
11:35
this next little bit is going
to take some focused typing.
11:39
So I recommend that you
approach it calm and refreshed.
11:42
Don't worry, I'll be right here waiting
for you just like Richard Marx, but
11:45
without the mullet.
11:49
See you in a bit.
11:50
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up