How to Integrate jCasbin with Spring Boot for Dynamic Permission Management

This article provides a step‑by‑step guide for backend developers to replace Shiro with jCasbin in a Spring Boot application, covering Maven dependencies, configuration files, Enforcer initialization, custom filter implementation, and runtime permission add/remove APIs, all with complete code examples.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
How to Integrate jCasbin with Spring Boot for Dynamic Permission Management

Overview

This guide shows how to integrate jCasbin into a Spring Boot application for fine‑grained permission control. An Enforcer is created from a Casbin model file and a policy source (e.g., a MySQL database). A servlet filter delegates each request to enforcer.enforce(user, path, method), and policies can be added or removed at runtime via simple REST endpoints.

Dependencies

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

Configuration

Create a @ConfigurationProperties class to hold database connection details and the path to the Casbin model file.

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

Add matching entries to application.properties (adjust values for your environment):

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

Enforcer initialization

Implement a Spring component that creates the Enforcer when the application context starts. The component also provides static helper methods for adding, removing, and retrieving the enforcer.

@Component
public class EnforcerFactory implements InitializingBean {
    private static Enforcer enforcer;
    @Autowired
    private EnforcerConfigProperties props;

    @Override
    public void afterPropertiesSet() throws Exception {
        JDBCAdapter adapter = new JDBCAdapter(
                props.getDriverClassName(),
                props.getUrl(),
                props.getUsername(),
                props.getPassword(),
                true);
        enforcer = new Enforcer(props.getModelPath(), adapter);
        enforcer.loadPolicy();
    }

    public static boolean addPolicy(Policy p) {
        boolean ok = enforcer.addPolicy(p.getSub(), p.getObj(), p.getAct());
        enforcer.savePolicy();
        return ok;
    }

    public static boolean removePolicy(Policy p) {
        boolean ok = enforcer.removePolicy(p.getSub(), p.getObj(), p.getAct());
        enforcer.savePolicy();
        return ok;
    }

    public static Enforcer getEnforcer() {
        return enforcer;
    }
}

Define a simple POJO to represent a policy rule.

public class Policy {
    private String sub; // user or role
    private String obj; // resource path, e.g. /user/*
    private String act; // HTTP method, 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
}

Permission enforcement

Servlet filter

Register a @WebFilter that obtains the shared Enforcer and decides whether a request should proceed.

@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 req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        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("Access denied for user {} on {} {}", user, path, method);
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":1001,\"msg\":\"User permission insufficient\",\"data\":null}");
        }
    }
    // init and destroy methods omitted
}

Dynamic policy management

Expose REST endpoints that call the static methods in EnforcerFactory to add or remove a policy without restarting the service.

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

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

Reference

Official jCasbin repository: https://github.com/casbin/jcasbin

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.