0% found this document useful (0 votes)
29 views12 pages

Spring Security Cheetsheet

The document provides a comprehensive guide on implementing Spring Security, detailing steps from basic setup to advanced configurations including JWT authentication. It covers the creation of user roles, security configurations, and the integration of JWT for stateless authentication. Additionally, it addresses the transition from deprecated components to newer practices in Spring Security.

Uploaded by

Suresh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views12 pages

Spring Security Cheetsheet

The document provides a comprehensive guide on implementing Spring Security, detailing steps from basic setup to advanced configurations including JWT authentication. It covers the creation of user roles, security configurations, and the integration of JWT for stateless authentication. Additionally, it addresses the transition from deprecated components to newer practices in Spring Security.

Uploaded by

Suresh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 12

Spring security cheetsheet:

---------------------------

@RestController
public class HelloController {
@GetMapping(path = "home")
public String home(){
return "home";
}
@GetMapping(path = "admin")
public String admin(){
return "admin";
}

@GetMapping(path = "mgr")
public String mgr(){
return "mgr";
}

@GetMapping(path = "clerk")
public String clerk(){
return "clerk";
}
}

step 1: put spring sec dependency

step 2: customized spring security

Spring 2.7.11
--------------
@Component
@EnableWebSecurity
public class SecConfig extends WebSecurityConfigurerAdapter {
//auth: Who are u? 401
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("raj").password("raj123").roles("MGR")
.and()
.withUser("ekta").password("ekta123").roles("CLERK");
}
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();//hey dont expect passwould be
encr...
}
//authorization
//I know who are you but u dont hv acces to this resoucce 403
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/mgr/**").hasAnyRole("MGR")
.antMatchers("/clerk/**").hasAnyRole("CLERK","MGR")
.antMatchers("/home/**").permitAll()
.and()
.httpBasic()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ST
ATELESS);
}
}

spring security 3.2.X


-----------------------

@Component
@EnableWebSecurity
@EnableMethodSecurity
public class SecConfig {
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder){
UserDetails raj= User.withUsername("raj")
.password(passwordEncoder.encode("raj123"))
.roles("ADMIN")
.build();
UserDetails ekta= User.withUsername("ekta")
.password(passwordEncoder.encode("ekta123"))
.roles("MGR")
.build();

UserDetails gun= User.withUsername("gun")


.password(passwordEncoder.encode("gun123"))
.roles("CLERK")
.build();
return new InMemoryUserDetailsManager(raj,ekta, gun);

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws
Exception {
http.csrf(AbstractHttpConfigurer::disable)
.cors(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(registry ->
registry.requestMatchers("/admin/**").hasAnyRole("ADMIN")

.requestMatchers("/mgr/**").hasAnyRole("ADMIN","MGR")

.requestMatchers("/clerk/**").hasAnyRole("ADMIN","MGR","CLERK")
.requestMatchers("/home/**").permitAll()
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.sessionManagement(httpSecuritySessionManagementConfigurer ->

httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy
.STATELESS));

return http.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}

Step 3: Spring sec with database

step 3 a:
define user entity
---------------------
@Data
@NoArgsConstructor
@ToString
@Entity
@Table(name = "user_table_2")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@Column(unique = true, nullable = false)


private String username;
private String password;

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name="user_roles_2")
private List<String> roles= new ArrayList<>();

public UserEntity(String username, String password, List<String> roles) {


this.username = username;
this.password = password;
this.roles = roles;
}
}

step 3 b: define repo


--------------------

@Repository
public interface UserRepo extends JpaRepository<UserEntity, Integer> {
public UserEntity findByUsername(String userName);
}

step 3 c: define service layer


-------------------------------

public interface UserService {


public UserEntity findByUsername(String username);
public void addUserEntity(UserEntity userEntity);
}

@Service
@Transactional
public class UserServiceImpl implements UserService{
private UserRepo userRepo;
@Autowired
public UserServiceImpl(UserRepo userRepo) {
this.userRepo = userRepo;
}

@Override
public UserEntity findByUsername(String username) {
return userRepo.findByUsername(username);
}

@Override
public void addUserEntity(UserEntity userEntity) {
userRepo.save(userEntity);
}
}

step 3 d: define userDetail service


--------------------------------------
@Service
public class DetailService implements UserDetailsService {

@Autowired
private UserService userService;

@Override
public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
UserEntity userEntity=userService.findByUsername(username);
if(userEntity==null)
throw new UsernameNotFoundException("Username/password is invalid");
//now problem: userEntity--->UserDetails(which spring sec understand)
return new SecUser(userEntity);
}
}

step 3 e: define secUser


-------------------------

public class SecUser implements UserDetails {

private UserEntity userEntity;

public SecUser(UserEntity userEntity) {


this.userEntity = userEntity;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<String> roles=userEntity.getRoles();
//somehow u need to createe AL to Array
String []rolesArray=roles.toArray(new String[roles.size()]);

return AuthorityUtils.createAuthorityList(rolesArray);
}

@Override
public String getPassword() {
return userEntity.getPassword();
}

@Override
public String getUsername() {
return userEntity.getUsername();
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}
}

step 3 f: initilized database


---------------------------
//String username, String password, List<String> roles
userService.addUserEntity(new UserEntity("raj","raj123",
List.of("ROLE_MGR","ROLE_CLERK")));
userService.addUserEntity(new UserEntity("ekta","ekta123", List.of("ROLE_CLERK")));

with password encoder:


---------------------------

userService.addUserEntity(new UserEntity("raj",passwordEncoder.encode("raj123"),
List.of("ROLE_MGR","ROLE_CLERK")));
userService.addUserEntity(new UserEntity("ekta",passwordEncoder.encode("ekta123"),
List.of("ROLE_CLERK")));

step 3 g: change security config to use user detailservice


--------------------------------------------------------

@Componenthome
@EnableWebSecurity
public class SecConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

//auth: Who are u? 401


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();//hey dont expect passwould be encr...
}
//authorization
//I know who are you but u dont hv acces to this resoucce 403
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/opertions/**").hasAnyRole("MGR")
.antMatchers("/api/transactions/**").hasAnyRole("CLERK","MGR")
.antMatchers("/home/**").permitAll()
.and()
.httpBasic()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ST
ATELESS);
}
}

Step 4: spring boot method level security


------------------------------------------
@Component
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
//@EnableMethodSecurity
public class SecConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

//auth: Who are u? 401


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();//hey dont expect passwould be encr...
}
//authorization
//I know who are you but u dont hv acces to this resoucce 403
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ST
ATELESS);
}
}

Applying method level security:


@PreAuthorize("hasAuthority('ROLE_MGR') or hasAuthority('ROLE_CLERK')")
@PreAuthorize("hasAuthority('ROLE_MGR')")

Step 5: WebSecurityConfigurerAdapter is deprecated


-----------------------------------------------------

@Component
@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableMethodSecurity
public class SecConfig {
@Autowired
private UserDetailsService userDetailsService;

@Bean
public AuthenticationProvider getAuthentication(){
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();//hey dont expect passwould be encr...
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http)throws Exception{
return http.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STA
TELESS)
.and()
.build();
}
}

Spring security jwt:


-------------------
step 1: put maven dependency
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>

Step 2: create JwtService that create and validate jwt token


------------------------------------------------------------

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoder;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

@Component
public class JwtService {
public static final String
SECRET =
"5367566B59703373367639792F423F4528482B4D6251655468576D5A71347437";

public String extractUsername(String token) {


return extractClaim(token, Claims::getSubject);
}

public Date extractExpiration(String token) {


return extractClaim(token, Claims::getExpiration);
}

public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {


final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}

private Claims extractAllClaims(String token) {


return Jwts
.parserBuilder()
.setSigningKey(getSignKey())
.build()
.parseClaimsJws(token)
.getBody();
}

private Boolean isTokenExpired(String token) {


return extractExpiration(token).before(new Date());
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !
isTokenExpired(token));
}

public String generateToken(String userName) {


Map<String, Object> claims = new HashMap<>();
return createToken(claims, userName);
}

private String createToken(Map<String, Object> claims, String userName) {


return Jwts.builder()
.setClaims(claims)
.setSubject(userName)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 *
30))
.signWith(getSignKey(), SignatureAlgorithm.HS256).compact();
}

private Key getSignKey() {


byte[] keyBytes = Decoders.BASE64.decode(SECRET);
return Keys.hmacShaKeyFor(keyBytes);
}
}

Step 2: create an endpoint "authenticate" that allow user to get jwt token
-----------------------------------------------------------------------------

@RestController
public class HelloController {

@Autowired
private JwtService jwtService;

@Autowired
private AuthenticationManager authenticationManager;

@GetMapping(path = "home")
public String home() {
return "home ";
}

//3. craete a endpoint so that user can send his u/p and get token
@PostMapping(path = "authenticate")
public String authenticateAndGetToken(@RequestBody AuthRequest authRequest) {

Authentication authentication
=authenticationManager.
authenticate(new UsernamePasswordAuthenticationToken(
authRequest.getUsername(),
authRequest.getPassword()
));

if(authentication.isAuthenticated()){
return jwtService.generateToken(authRequest.getUsername());
}else {
throw new UsernameNotFoundException("user is invalid");
}

@PreAuthorize("hasAuthority('ROLE_MGR')")
@GetMapping(path = "mgr")
public String mgr(){
return "mgr ";
}

@PreAuthorize("hasAuthority('ROLE_MGR') or hasAuthority('ROLE_CLERK')")
@GetMapping(path = "clerk")
public String clerk(){
return "clerk ";
}

Step 3: write JwtAuthFilter that validate jwt token and put


UsernamePasswordAuthenticationToken in security context
-----------------------------------------------------------------------------

@Service
public class JwtAuthFilter extends OncePerRequestFilter {

@Autowired
private JwtService jwtService;

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
response, FilterChain filterChain)
throws ServletException, IOException {

String authHeader= request.getHeader("Authorization");


String token=null;
String username=null;

if(authHeader!=null && authHeader.startsWith("Bearer ")){


token=authHeader.substring(7);
username=jwtService.extractUsername(token);
}

if(username!=null &&
SecurityContextHolder.getContext().getAuthentication()==null){
UserDetails
userDetails=userDetailsService.loadUserByUsername(username);
//username is correct , and we are going to get UNAuthToeken and put
that in SecurityContextHolder ....
if(jwtService.validateToken(token, userDetails)){

UsernamePasswordAuthenticationToken authToken=
new UsernamePasswordAuthenticationToken(userDetails, null,
userDetails.getAuthorities());

// authToken.setDetails(new
WebAuthenticationDetailsSource().buildDetails(request));

SecurityContextHolder.getContext().setAuthentication(authToken);

}
filterChain.doFilter(request, response);
}
}

Step 4: Customized spring security so that jwtAuthFilter must be registerd before


UsernamePasswordAuthenticationFilter
-----------------------------------------------------------------------------

@Component
@EnableWebSecurity(debug = true)
//@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableMethodSecurity
public class SecConfig {
@Autowired
private UserDetailsService userDetailsService;

@Autowired
private JwtAuthFilter jwtAuthFilter;

//auth: Who are u? 401


@Bean
public AuthenticationProvider getAuthentication(){
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();//hey dont expect passwould be encr...
}
//authorization
//I know who are you but u dont hv acces to this resoucce 403

//4. let allow to bypass "authenticate"


@Bean
public SecurityFilterChain filterChain(HttpSecurity http)throws Exception{
return http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/home","/authenticate").permitAll()
.and()
.authorizeHttpRequests().requestMatchers("/**")
.authenticated()
.and()
.httpBasic()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STA
TELESS)
.and()
.authenticationProvider(getAuthentication())
.addFilterBefore(jwtAuthFilter,
UsernamePasswordAuthenticationFilter.class)
.build();
}
//5. get the AM
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration
config)throws Exception {
return config.getAuthenticationManager();
}
}

You might also like