Backend Development 9 min read

Integrating jCasbin Permission Management into Spring Boot Applications

This article introduces jCasbin as a lightweight alternative to Shiro for permission management in Spring Boot, explains Maven setup, configuration files, Enforcer initialization, policy model definition, and demonstrates how to enforce, add, and delete permissions dynamically using filters and REST endpoints.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Integrating jCasbin Permission Management into Spring Boot Applications

Introduction

As a backend developer, the author discusses the drawbacks of using Shiro for permission management in distributed Spring Cloud projects and introduces jCasbin as a lightweight alternative.

1. Preparation

Shows Maven dependencies for jCasbin and its JDBC adapter:

<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>

The framework stores role‑permission mappings in model.conf and policy.csv , which can also be loaded from a database.

2. Configuration

A Spring @ConfigurationProperties class loads DB connection details and the model file path, and the following entries are added to application.properties :

org.jcasbin.url=jdbc:mysql://localhost:3306/casbin?useSSL=false
org.jcasbin.driver-class-name=com.mysql.jdbc.Driver
org.jcasbin.username=root
org.jcasbin.password=root
org.jcasbin.model-path=conf/authz_model.conf

3. Initializing Enforcer

An EnforcerFactory implements InitializingBean to create a static Enforcer using a JDBCAdapter that reads policies from the database. It also provides static methods to add and remove policies.

@Component
public class EnforcerFactory implements InitializingBean {
    private static Enforcer enforcer;
    @Autowired
    private EnforcerConfigProperties enforcerConfigProperties;
    @Override
    public void afterPropertiesSet() throws Exception {
        EnforcerConfigProperties config = enforcerConfigProperties;
        JDBCAdapter jdbcAdapter = new JDBCAdapter(config.getDriverClassName(), config.getUrl(), config.getUsername(), config.getPassword(), true);
        enforcer = new Enforcer(config.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; }
}

4. Policy Model

A simple POJO represents a permission entry:

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

5. Usage

A servlet filter checks permissions with enforcer.enforce(user, path, method) and returns a JSON error when access is denied.

@WebFilter(urlPatterns = "/*", filterName = "JCasbinAuthzFilter")
@Order(Ordered.HIGHEST_PRECEDENCE)
public class JCasbinAuthzFilter implements Filter {
    private static Enforcer enforcer;
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        String user = request.getParameter("username");
        String path = request.getRequestURI();
        String method = request.getMethod();
        enforcer = EnforcerFactory.getEnforcer();
        if (path.contains("anon") || enforcer.enforce(user, path, method)) {
            chain.doFilter(request, response);
        } else {
            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
}

Two REST endpoints demonstrate dynamic permission management 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();
}

Conclusion

The author notes that jCasbin can be combined with Spring Cloud Zuul to achieve unified login and permission control, which will be explored in future posts.

backendJavapermissionSpring BootAuthorizationjCasbin
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

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.