Backend Development 10 min read

Integrating jCasbin Permission Management into Spring Boot Applications

This article demonstrates how to add jCasbin to a Spring Boot project, covering Maven dependencies, configuration files, Enforcer initialization, custom policy objects, a servlet filter for authorization, and dynamic add‑remove permission APIs, enabling lightweight, database‑driven access control.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Integrating jCasbin Permission Management into Spring Boot Applications

As a backend developer, the author compares traditional Shiro permission management with the newer jCasbin library, noting Shiro's complexity in distributed Spring Cloud environments and introducing jCasbin as a simpler alternative.

1. Preparation

Add the jCasbin and JDBC adapter dependencies to your Maven pom.xml :

<dependency>
    <groupId>org.casbin</groupId>
    <artifactId>jcasbin</artifactId>
    <version>1.1.0</version>
</dependency>
<dependency>
    <groupId>org.casbin</groupId>
    <artifactId>jdbc-adapter</artifactId>
    <version>1.1.0</version>
</dependency>

Create a configuration class to bind properties from application.properties :

@Configuration
@ConfigurationProperties(prefix = "org.jcasbin")
public class EnforcerConfigProperties {
    private String url;
    private String driverClassName;
    private String username;
    private String password;
    private String modelPath;
    // getters and setters omitted for brevity
    @Override
    public String toString() {
        return "EnforcerConfigProperties [url=" + url + ", driverClassName=" + driverClassName + ", username=" + username + ", password=" + password + ", modelPath=" + modelPath + "]";
    }
}

Define the model and policy files ( model.conf and policy.csv ) and place them alongside the src directory. The policy can also be loaded from a database.

2. Initialize Permission Information

Implement a factory that creates a singleton Enforcer during Spring's startup by implementing InitializingBean :

@Component
public class EnforcerFactory implements InitializingBean {
    private static Enforcer enforcer;
    @Autowired
    private EnforcerConfigProperties enforcerConfigProperties;
    @Override
    public void afterPropertiesSet() throws Exception {
        // Load policy from DB via JDBCAdapter
        JDBCAdapter jdbcAdapter = new JDBCAdapter(
            enforcerConfigProperties.getDriverClassName(),
            enforcerConfigProperties.getUrl(),
            enforcerConfigProperties.getUsername(),
            enforcerConfigProperties.getPassword(), true);
        enforcer = new Enforcer(enforcerConfigProperties.getModelPath(), jdbcAdapter);
        enforcer.loadPolicy();
    }
    public static boolean addPolicy(Policy policy) {
        boolean added = enforcer.addPolicy(policy.getSub(), policy.getObj(), policy.getAct());
        enforcer.savePolicy();
        return added;
    }
    public static boolean removePolicy(Policy policy) {
        boolean removed = enforcer.removePolicy(policy.getSub(), policy.getObj(), policy.getAct());
        enforcer.savePolicy();
        return removed;
    }
    public static Enforcer getEnforcer() { return enforcer; }
}

Define a simple POJO to represent a policy entry:

public class Policy {
    private String sub; // user or role
    private String obj; // resource, e.g., /user/*
    private String act; // action, e.g., GET, POST
    public Policy() {}
    public Policy(String sub, String obj, String act) {
        this.sub = sub; this.obj = obj; this.act = act;
    }
    // getters and setters omitted
    @Override
    public String toString() {
        return "Policy[sub=" + sub + ", obj=" + obj + ", act=" + act + "]";
    }
}

3. Usage

3.1 Permission Filter

Create a servlet filter that checks each request against the Enforcer :

@WebFilter(urlPatterns = "/*", filterName = "JCasbinAuthzFilter")
@Order(Ordered.HIGHEST_PRECEDENCE)
public class JCasbinAuthzFilter implements Filter {
    private static final Logger log = LoggerFactory.getLogger(JCasbinAuthzFilter.class);
    private static Enforcer enforcer;
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String user = request.getParameter("username");
        String path = request.getRequestURI();
        String method = request.getMethod();
        enforcer = EnforcerFactory.getEnforcer();
        if (path.contains("anon")) {
            chain.doFilter(request, response);
        } else if (enforcer.enforce(user, path, method)) {
            chain.doFilter(request, response);
        } else {
            log.info("Unauthorized access");
            Map
result = new HashMap<>();
            result.put("code", 1001);
            result.put("msg", "User lacks permission");
            result.put("data", null);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            response.getWriter().write(JSONObject.toJSONString(result, SerializerFeature.WriteMapNullValue));
        }
    }
    // init and destroy omitted
}

3.2 Adding and Removing Permissions at Runtime

Expose REST endpoints that call the factory methods, allowing policies to be added or removed without restarting the service:

@PutMapping("/anon/role/per")
public ResultBO
addPer() {
    EnforcerFactory.addPolicy(new Policy("alice", "/user/list", "*"));
    return ResultTool.success();
}

@DeleteMapping("/anon/role/per")
public ResultBO
deletePer() {
    EnforcerFactory.removePolicy(new Policy("alice", "/user/list", "*"));
    return ResultTool.success();
}

Finally, the author notes that the same approach can be combined with Spring Cloud Zuul by implementing a custom ZuulFilter , achieving unified login and permission control across micro‑services.

backendJavapermissionSpring BootAuthorizationjCasbin
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.