Skip to content

Commit bec1752

Browse files
committed
SpringBoot Security
1 parent cef8248 commit bec1752

File tree

8 files changed

+172
-1
lines changed

8 files changed

+172
-1
lines changed

SpringBoot Security.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,11 +1250,117 @@ Disabling csrf
12501250
> - As per Spring Security 6+ the recommended hash function is **BCrypt**. If in future if this BcryptPasswordEncoder has becomes weak, then obviously Spring Security team is going to move on to the more advanced password encoder and they're going to make that as a default one.
12511251
12521252
1253+
## Custom Authentication Provider
12531254
1255+
- Uptil now we have used the in-build Authentication provider (**DaoAuthenticationProvider**) to authenticate user by loading the details from database. So with the help of **UserDetailsService** , **DaoAuthenticationProvider** authenticates the user is valid or or not.
1256+
- The **DaoAuthenticationProvider** is an implementation of **AuthenticationProvider** that uses a **UserDetailsService** to retrieve user details from a data source (like a database). When a user tries to authenticate (e.g., by logging in), the **DaoAuthenticationProvider**:
1257+
- Uses the **UserDetailsService** to load the user details (such as username, password, and roles) from the database.
1258+
- Compares the provided credentials (e.g., the password entered by the user) with the stored credentials in the database.
1259+
- If the credentials match, the user is authenticated successfully.
1260+
- This process ensures that only valid users with correct credentials can access protected resources in your application.
12541261
1262+
- What if you wanna have your own custom authentication provider? , lets say suppose you wanna authenticate based on country location? or based on age? , lets say you are building a website and you have alternative ways like user can register via Gmail, meta or any other third party . Lets say you wanna also implement OAuth ? so you need to customized your authentication provider.
1263+
- In such case , you need to have multiple authentication providers, but how will you manage those authentication providers? for that we will have layer called **ProviderManager**, but how the **ProviderManager** knows which authentication provider to call when the user tries to access the protected pages? like when user is login via gmail call the gmail authentication provider, if user is tries to login via meta then call the meta authentication provider? , the **ProviderManager** will come to know about it based on the **Type of Authentication Object**.
12551264
12561265
1266+
![alt text](image-57.png)
12571267
1268+
- Before we try to implement our own **AuthenticationProvider** , first lets try to understand about how it works?
1269+
1270+
![alt text](image-58.png)
1271+
1272+
- The **AuthenticationProvider** consist of two methods `authenticate()` and `supports()`. Lets try to understand these methods.
1273+
- `authenticate(Authentication authentication)`: This method attempts to authenticate the user based on the provided Authentication object (e.g., containing the username and password). If successful, it returns a fully authenticated Authentication object. If authentication fails, it can throw an exception.
1274+
- `supports(Class<?> authentication)`: This method checks whether the **AuthenticationProvider** can handle the given type of Authentication object. For example, **DaoAuthenticationProvider** typically supports **UsernamePasswordAuthenticationToken**.
1275+
1276+
- The **UsernamePasswordAuthenticationFilter** is a Spring Security filter that intercepts login requests (usually HTTP POST requests to /login) and attempts to authenticate the user using the provided username and password. This filter:
1277+
- Creates an Authentication object (usually **UsernamePasswordAuthenticationToken**) using the provided username and password.
1278+
Passes this Authentication object to the **AuthenticationManager** for authentication.
1279+
- The **ProviderManager** is the default implementation of **AuthenticationManager** in Spring Security.
1280+
1281+
![alt text](image-59.png)
1282+
1283+
- **ProviderManager** holds a list of **AuthenticationProviders**.
1284+
- When its `authenticate()` method is called (e.g., by **UsernamePasswordAuthenticationFilter**), it iterates through its list of **AuthenticationProviders**.
1285+
- For each **AuthenticationProvider**, it checks if it supports the **type of Authentication object (using the supports() method)**.
1286+
- Once it finds a suitable **AuthenticationProvider**, it calls its authenticate() method.
1287+
- If authentication is successful, it returns the authenticated Authentication object; otherwise, it tries the next provider or throws an exception if no provider can authenticate the user.
1288+
1289+
- Lets create a custom authentication method. **Your custom authentication should be a bean thats why it is important to annotate it with `@Component`**.
1290+
1291+
```
1292+
package com.springboot.security.authenticationprovider;
1293+
1294+
import org.springframework.security.authentication.AuthenticationProvider;
1295+
import org.springframework.security.authentication.BadCredentialsException;
1296+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
1297+
import org.springframework.security.core.Authentication;
1298+
import org.springframework.security.core.AuthenticationException;
1299+
import org.springframework.security.core.userdetails.UserDetails;
1300+
import org.springframework.security.crypto.password.PasswordEncoder;
1301+
import org.springframework.stereotype.Component;
1302+
1303+
import com.springboot.security.service.*;
1304+
import lombok.RequiredArgsConstructor;
1305+
1306+
@RequiredArgsConstructor
1307+
@Component
1308+
public class CustomAuthenticationProvider implements AuthenticationProvider{
1309+
1310+
private final CustomerService customerService;
1311+
private final PasswordEncoder passwordEncoder;
1312+
1313+
@Override
1314+
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
1315+
/**
1316+
* Input from page or API
1317+
*/
1318+
String inputMailId=authentication.getName();
1319+
String inputPwd=authentication.getCredentials().toString();
1320+
1321+
/**
1322+
* Custom logic like age > 10 here we are just specifying user must be abc@gmail.com only
1323+
* PasswordEncoder is require to perform encoded match between the input entered password and the password
1324+
* in database
1325+
*/
1326+
if(!("abc@gmail.com").equals(inputMailId)) {
1327+
System.out.println("UnAuthorized Email ID, message from Custom Authentication");
1328+
throw new BadCredentialsException("UnAuthorized Email ID, message from Custom Authentication");
1329+
}
1330+
1331+
1332+
/**
1333+
* Fetch Details from database
1334+
*/
1335+
UserDetails uc=customerService.loadUserByUsername(inputMailId);
1336+
1337+
if(passwordEncoder.matches(inputPwd, uc.getPassword())) {
1338+
return new UsernamePasswordAuthenticationToken(uc.getUsername(),uc.getPassword(),uc.getAuthorities());
1339+
}
1340+
1341+
/**
1342+
* AuthenticationException is an abstract class which is implemented by multiple exceptions like
1343+
* - BadCredentialsException
1344+
* - UsernameNotFoundException ( this exception is thrown by loadByUserName of UserDetailsService )
1345+
* .. and many more
1346+
*/
1347+
throw new BadCredentialsException("Invalid Credentials");
1348+
}
1349+
1350+
@Override
1351+
public boolean supports(Class<?> authentication) {
1352+
// TODO Auto-generated method stub
1353+
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
1354+
}
1355+
1356+
}
1357+
1358+
Output:
1359+
mo.s.s.a.ProviderManager- Authenticating request with CustomAuthenticationProvider (1/1)
1360+
UnAuthorized Email ID, message from Custom Authentication
1361+
```
1362+
1363+
![alt text](image-60.png)
12581364
12591365
12601366
17 MB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.springboot.security.authenticationprovider;
2+
3+
import org.springframework.security.authentication.AuthenticationProvider;
4+
import org.springframework.security.authentication.BadCredentialsException;
5+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
6+
import org.springframework.security.core.Authentication;
7+
import org.springframework.security.core.AuthenticationException;
8+
import org.springframework.security.core.userdetails.UserDetails;
9+
import org.springframework.security.crypto.password.PasswordEncoder;
10+
import org.springframework.stereotype.Component;
11+
12+
import com.springboot.security.service.*;
13+
import lombok.RequiredArgsConstructor;
14+
15+
@RequiredArgsConstructor
16+
@Component
17+
public class CustomAuthenticationProvider implements AuthenticationProvider{
18+
19+
private final CustomerService customerService;
20+
private final PasswordEncoder passwordEncoder;
21+
22+
@Override
23+
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
24+
/**
25+
* Input from page or API
26+
*/
27+
String inputMailId=authentication.getName();
28+
String inputPwd=authentication.getCredentials().toString();
29+
30+
/**
31+
* Custom logic like age > 10 here we are just specifying user must be abc@gmail.com only
32+
* PasswordEncoder is require to perform encoded match between the input entered password and the password
33+
* in database
34+
*/
35+
if(!("abc@gmail.com").equals(inputMailId)) {
36+
System.out.println("UnAuthorized Email ID, message from Custom Authentication");
37+
throw new BadCredentialsException("UnAuthorized Email ID, message from Custom Authentication");
38+
}
39+
40+
41+
/**
42+
* Fetch Details from database
43+
*/
44+
UserDetails uc=customerService.loadUserByUsername(inputMailId);
45+
46+
if(passwordEncoder.matches(inputPwd, uc.getPassword())) {
47+
return new UsernamePasswordAuthenticationToken(uc.getUsername(),uc.getPassword(),uc.getAuthorities());
48+
}
49+
50+
/**
51+
* AuthenticationException is an abstract class which is implemented by multiple exceptions like
52+
* - BadCredentialsException
53+
* - UsernameNotFoundException ( this exception is thrown by loadByUserName of UserDetailsService )
54+
* .. and many more
55+
*/
56+
throw new BadCredentialsException("Invalid Credentials");
57+
}
58+
59+
@Override
60+
public boolean supports(Class<?> authentication) {
61+
// TODO Auto-generated method stub
62+
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
63+
}
64+
65+
}

SpringBoot Security/security/src/main/resources/application.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ spring.datasource.password=Meetpandya40@
99
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
1010
spring.jpa.database-platform = org.hibernate.dialect.MySQL8Dialect
1111
spring.jpa.generate-ddl=true
12-
spring.jpa.hibernate.ddl-auto = create
12+
spring.jpa.hibernate.ddl-auto = update
1313
spring.jpa.show-sql=true

image-57.png

225 KB
Loading

image-58.png

343 KB
Loading

image-59.png

72.9 KB
Loading

image-60.png

32.4 KB
Loading

0 commit comments

Comments
 (0)