Backend Development 10 min read

Integrating jCasbin Permission Management into Spring Boot Applications

This article demonstrates how to replace Shiro with jCasbin for fine‑grained permission control in a Spring Boot 1.5.10 project, covering Maven dependencies, configuration files, Enforcer initialization, a custom servlet filter, and dynamic policy add/remove APIs.

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

As a backend developer, the author finds Shiro cumbersome for distributed Spring Cloud projects and introduces jCasbin as a lightweight alternative for permission management.

1. Preparation

Add the following Maven dependencies to your 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>

2. Configuration files

Place model.conf in a folder parallel to src and configure policy.csv (or load it from a database). Example application.properties entries:

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. Enforcer initialization

Create a configuration class EnforcerConfigProperties to bind the above properties, then implement an EnforcerFactory that implements InitializingBean to instantiate the Enforcer and load policies from the database:

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

The Policy class simply holds sub , obj , and act fields with getters/setters.

4. Permission filter

Implement a servlet filter that obtains the current user, request path, and HTTP method, then calls enforcer.enforce(user, path, method) to decide whether to allow the request:

@WebFilter(urlPatterns = "/*", filterName = "JCasbinAuthzFilter")
@Order(Ordered.HIGHEST_PRECEDENCE)
public class JCasbinAuthzFilter implements Filter {
    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 {
            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 for brevity
}

5. Dynamic policy management

Expose REST endpoints that call the static methods of EnforcerFactory to add or remove 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();
}

Finally, the author notes that jCasbin can be combined with Spring Cloud Zuul for unified login and permission control, which will be covered in a future article.

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