Spring Security 根据角色显示菜单是否可见

来源:互联网 发布:工厂模式 java 编辑:程序博客网 时间:2024/05/21 08:36

1 角色和资源映射关系确定

应用所需要的角色以及对应的资源在代码完成之后就已经完全确定,项目部署之后,不会有变动。这里可以使用spring的标准标签语言来实现

  • 权限配置代码
@Overrideprotected void configure(HttpSecurity http) throws Exception {        http.authorizeRequests().antMatchers("/", "/list")                .access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")                .antMatchers("/newuser/**", "/delete-user-*").access("hasRole('ADMIN')").antMatchers("/edit-user-*")                .access("hasRole('ADMIN') or hasRole('DBA')").and().formLogin().loginPage("/login")                .loginProcessingUrl("/login").usernameParameter("ssoId").passwordParameter("password").and()                .rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository)                .tokenValiditySeconds(86400).and().csrf().and().exceptionHandling().accessDeniedPage("/Access_Denied");    }
  • 展示层代码
<sec:authorize access="hasRole('ADMIN') or hasRole('DBA')">    <td><a href="<c:url value='/edit-user-${user.ssoId}' />" class="btn btn-success custom-width">edit</a></td></sec:authorize><sec:authorize access="hasRole('ADMIN')">    <td><a href="<c:url value='/delete-user-${user.ssoId}' />" class="btn btn-danger custom-width">delete</a></td></sec:authorize>

2 角色-资源映射关系动态变化

应用部署之后,角色和资源会动态修改。Spring标签就没办法实现了。
我的实现方式是,新写一个自己的展示层标签。在展示层代码中,将需要根据权限判断是否需要显示的代码片段写在自定义标签之中。
以freemarker为例,freemarker提供了一种自定义标签的实现方式,参考链接:http://freemarker.org/docs/pgui_datamodel_directive.html

  • Java代码:
public class CheckPermission implements TemplateDirectiveModel {    AdminService adminService = (AdminService) SpringUtil.getBean("adminServiceImpl");    @Override    public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)            throws TemplateException, IOException {        // 禁止循环变量        if (loopVars.length != 0) {            throw new TemplateModelException("This directive doesn't allow loop variables.");        }        Object paramValue = params.get("resource");        String resource = ((SimpleScalar) paramValue).getAsString();        Admin admin = adminService.loadLoginAdmin();        if (null == admin) {            return;        }        Set<Role> roleSet = admin.getRoleSet();        boolean flag = false;        for (Role role : roleSet) {            if (!flag) {                Set<Resources> resourcesSet = role.getResourcesSet();                for (Resources resources : resourcesSet) {                    if (resource.equals(resources.getValue())) {                        body.render(env.getOut());                        flag = true;                        break;                    }                }            } else {                break;            }        }    }    private HttpServletRequest getRequest() {        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();        HttpServletRequest request = attr.getRequest();        return request;    }}
  • ftl页面代码:
<#assign checkPermission = "CheckPermission"?new()><@checkPermission resource="http://www.baidu.com"><input  type="button"onclick="window.location.href='http://www.baidu.com';" value="1.百度一下"></@checkPermission>
1 0