Understanding RBAC and Implementing Spring Security with JWT in Java
This article explains the concepts and models of Role‑Based Access Control (RBAC), demonstrates how to configure Spring Security for in‑memory and JWT‑based authentication, and provides complete Java code examples for permissions, user groups, password encryption, and custom login filters.
The article begins with an overview of RBAC (Role‑Based Access Control), describing its purpose, the four RBAC models (RBAC0‑RBAC3), and how roles, users, and permissions relate. It illustrates typical scenarios such as assigning multiple roles to a user and the benefits of using role groups to simplify permission management.
Next, the article shows how to set up Spring Security for a simple in‑memory authentication example. It adds the required Maven dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>A basic controller is created:
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class Test {
@RequestMapping("/test")
public String test(){
return "test";
}
}Configuration for in‑memory users is provided using WebSecurityConfigurerAdapter :
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("123").roles("admin");
}
}To protect all endpoints, an HttpSecurity configuration is added that permits all requests for demonstration purposes while showing how to restrict access:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().permitAll()
.and()
.formLogin().permitAll()
.and()
.logout().permitAll();
}The article then moves to JWT integration. It adds the JWT library dependency:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>A JwtTokenUtil class is provided to generate, parse, refresh, and validate tokens:
public class JwtTokenUtil implements Serializable {
private String secret;
private Long expiration;
private String header;
// generateToken, getClaimsFromToken, getUsernameFromToken, isTokenExpired, refreshToken, validateToken methods ...
}A filter JwtAuthenticationTokenFilter extracts the token from the request header, validates it, and sets the authentication in the security context:
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authHeader = request.getHeader(jwtTokenUtil.getHeader());
if (authHeader != null && StringUtils.isNotEmpty(authHeader)) {
String username = jwtTokenUtil.getUsernameFromToken(authHeader);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authHeader, userDetails)) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}The final security configuration registers the JWT filter, disables CSRF, sets the session policy to stateless, and permits the authentication endpoints:
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}Additionally, the article covers password encryption using BCryptPasswordEncoder , custom JSON login by extending UsernamePasswordAuthenticationFilter , and database‑backed authentication with role‑based access control. It concludes with a summary that the reader now understands RBAC concepts, Spring Security configuration, JWT integration, and secure password handling.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.