30-11-2024
------------------------
open mysql
1)create database
----------------
create database klu_role_based_auth;
use klu_role_based_auth;
create table Role(id int primary key auto_increment,name varchar(20));
desc Role;
create table User(id int primary key auto_increment,username varchar(20),password
varchar(20));
desc User;
2)create springboot app application
Project name : RoleBasedAuthentication
dependencies
Mysql driver
spring web
spring boot dev tools
spring security
spring data jpa
open application.properties
----------------------------------
spring.application.name=RoleBasedAuthentication
# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/klu_role_based_auth
spring.datasource.username=root
spring.datasource.password=vijay
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Hibernate Configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
# Server Port (Optional)
server.port=9090
3)create Role model in
com.klu.model
Role.java
-------------------
package com.klu.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
public Role() {
super();
// TODO Auto-generated constructor stub
}
public Role(Long id, String name) {
super();
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
@Override
public String toString() {
return "Role [id=" + id + ", name=" + name + "]";
}
4)create User model
com.klu.model
User.java
-----------------
package com.klu.model;
import java.util.Set;
import com.klu.model.Role;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinTable;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToMany;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String username;
private String password;
@ManyToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
@JoinTable(
name="user_roles",
joinColumns=@JoinColumn(name="user_id"),
inverseJoinColumns=@JoinColumn(name="role_id")
)
private Set<Role> roles;
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(Long id, String username, String password, Set<Role> roles) {
super();
this.id = id;
this.username = username;
this.password = password;
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password
+ ", roles=" + roles + "]";
}
5)
goto com.klu
right click create package
com.klu.repository
right click create interface
UserRepository
----------------------
package com.klu.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.klu.model.User;
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
Optional<User> findByUsername(String username);
}
6)
create package
com.klu.security
DataLoader.java
---------------------------------
package com.klu.security;
import java.util.Set;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.klu.model.Role;
import com.klu.model.User;
import com.klu.repository.UserRepository;
@Configuration
public class DataLoader {
@Bean
public CommandLineRunner loadData(UserRepository userRepository,PasswordEncoder
passwordEncoder) {
return args->{
Role adminRole = new Role();
adminRole.setName("ROLE_ADMIN");
User admin = new User();
admin.setUsername("admin");
admin.setPassword(passwordEncoder.encode("admin"));
admin.setRoles(Set.of(adminRole));
Role userRole = new Role();
userRole.setName("ROLE_USER");
User user = new User();
user.setUsername("user");
user.setPassword(passwordEncoder.encode("user"));
user.setRoles(Set.of(userRole));
userRepository.save(admin);
userRepository.save(user);
};
}
}
7)create package
com.klu.security.config
right click
SecurityConfig.java
-------------------------------------
package com.klu.security.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.stereotype.Component;
@Configuration
public class SecurityConfig {
private final CustomAccessDeniedHandler customAccessDeniedHandler;
public SecurityConfig(CustomAccessDeniedHandler customAccessDeniedHandler) {
this.customAccessDeniedHandler = customAccessDeniedHandler;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)throws
Exception{
http.csrf()
.disable()
.authorizeRequests()
.requestMatchers("/admin").hasRole("ADMIN")
.requestMatchers("/user").hasRole("USER")
.requestMatchers("/").permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler(customAccessDeniedHandler)
.and()
.httpBasic();
return http.build();
}
}
CustomAccessDeniedHandler
---------------------------
package com.klu.security.config;
import java.io.IOException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException,
ServletException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType("application/json");
response.getWriter().write("{\"error\":\"access denied\"}");
}
}
8)create controller with following fields
com.klu.controller
KLUController.java
----------------------
package com.klu.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin("/")
public class KLUController {
@GetMapping("/")
public String home() {
return "welcome to klu";
}
@GetMapping("/admin")
public String admin() {
return "welcome to admin";
}
@GetMapping("/user")
public String user() {
return "welcome to user";
}
}
9)
customize spring security framework
com.klu.security.service
CustomUserDetails.java
--------------------------
package com.klu.security.service;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.klu.model.User;
public class CustomUserDetails implements UserDetails {
/**
*
*/
private static final long serialVersionUID = 1L;
private final User user;
public CustomUserDetails (User user) {
this.user=user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return user.getRoles().stream().map(role -> new
SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return user.getPassword();
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return user.getPassword();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
CustomUserDetailsService.java
---------------------
package com.klu.security.service;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.klu.model.User;
import com.klu.repository.UserRepository;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
// TODO Auto-generated method stub
User user = userRepository.findByUsername(username).orElseThrow(()-> new
UsernameNotFoundException("user not found"));
return new CustomUserDetails(user);
}
}
project right click
RoleBasedAuthentication
run as Spring Boot App
open mysql
select * from role;
select * from user;
open browser
http://localhost:9090
http://localhost:9090/admin
username : admin
password : admin