Designing Permission Control in a Front‑End/Back‑End Separated Architecture
This article explains how permission control is re‑thought for front‑end/back‑end separated systems, defining resources and permissions, outlining the distinct responsibilities of the front‑end and back‑end, and providing concrete implementation examples with component‑level checks and server‑side interceptors.
In a front‑end/back‑end separated architecture, all interaction scenarios become data‑driven, making traditional permission control schemes unsuitable for the front‑end and prompting a redesign of access control.
Two core concepts are introduced: resources – any system element such as pages, data, buttons, images, or even visual separators – and permissions – identifiers required to access those resources. A user’s permission set, calculated at login, determines which resources they can reach, which is the essence of permission control.
The article clarifies the responsibilities of each side. The back‑end provides data APIs, while the front‑end handles routing and page rendering. Because the front‑end controls the user interface, it must enforce permission checks on routes and on individual components (buttons, tables, separators, etc.), effectively applying permission control at the component level.
Example of a permission‑aware component:
<组件 permissionName='xxx' />Front‑end route guards store the user's permission identifiers after login and evaluate them on each navigation. Sample code:
let hasPermission = permission.check(current.permissionName);
{hasPermission ? children : <Exception type={403}/>}A reusable button component can encapsulate this logic:
<BirdButton permissionName={'sys'} type='primary'>测试按钮</BirdButton>On the back‑end, permission verification is performed via an interceptor that checks the required permissions before allowing the request to proceed. Sample Java interceptor:
public class SsoAuthorizeInterceptor extends HandlerInterceptorAdapter {
@Autowired
private TicketHandler ticketHandler;
@Autowired
private SsoAuthorizeManager authorizeManager;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) return false;
HandlerMethod handlerMethod = (HandlerMethod) handler;
SsoAuthorize authorize = handlerMethod.getMethodAnnotation(SsoAuthorize.class);
if (authorize != null) {
TicketInfo ticketInfo = ticketHandler.getTicket(request);
if (ticketInfo == null) {
throw new UnAuthorizedException("用户信息已失效.");
}
String[] requirePermissions = authorize.permissions();
if (requirePermissions.length == 0) return true;
boolean isCheckAll = authorize.isCheckAll();
UserPermissionChecker permissionChecker = authorizeManager.getUserPermissionChecker();
if (!permissionChecker.hasPermissions(ticketInfo.getUserId(), requirePermissions, isCheckAll)) {
throw new ForbiddenException("用户没有当前操作的权限.");
}
}
return true;
}
}The article also provides links to the source repository and related UI components (bird‑selector, bird‑grid, bird‑tree‑grid, bird‑tree, bird‑form, bird‑button) that demonstrate how to combine server APIs with front‑end components for rapid, secure business development.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.