Backend Development 10 min read

Integrating jCasbin Permission Management into Spring Boot Applications

This article explains how backend developers can replace Shiro with jCasbin for permission management in Spring Boot projects, covering Maven dependencies, configuration files, property loading, Enforcer initialization, custom policy objects, request filtering, and dynamic policy updates.

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

As a backend developer, the article introduces jCasbin as an alternative to Shiro for permission management in Spring Boot projects.

It first shows how to add the required 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 roles and permissions in two configuration files, model.conf and policy.csv , and can also load them from a database. An example application.properties configuration is provided:

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

A EnforcerConfigProperties class is defined to bind these properties, and an EnforcerFactory implements InitializingBean to create a static Enforcer instance using the model file and a JDBCAdapter that reads policies from the database.

@Component
public class EnforcerFactory implements InitializingBean {
    private static Enforcer enforcer;
    @Autowired
    private EnforcerConfigProperties enforcerConfigProperties;
    private static EnforcerConfigProperties config;
    @Override
    public void afterPropertiesSet() throws Exception {
        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; }
}

The Policy POJO encapsulates the three fields required by jCasbin: sub (subject), obj (object), and act (action).

public class Policy {
    private String sub;
    private String obj;
    private String act;
    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 + "]";
    }
}

For runtime permission checks, a web filter ( JCasbinAuthzFilter ) extracts the username, request path, and HTTP method, then calls enforcer.enforce(user, path, method) . If the check fails, a JSON error response is returned.

@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 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")) {
            chain.doFilter(request, response);
        } else if (enforcer.enforce(user, path, method)) {
            chain.doFilter(request, response);
        } else {
            log.info("无权访问");
            Map
result = new HashMap<>();
            result.put("code", 1001);
            result.put("msg", "用户权限不足");
            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 how to add or delete policies 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();
}

The article concludes that jCasbin can be combined with Spring Cloud Zuul to achieve 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.