Spring Security-- 使用权限编码控制权限

spring security中,如果权限字符以"ROLE_"开头,者可以使用@PreAuthorize("hasRole('ROLE_ADMIN')")注解匹配,其他使用@PreAuthorize("hasAuthority('user:write')")注解匹配

  • 修改建表结构

CREATE TABLE `permission` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL COMMENT 'url',
  `permission` varchar(255) NOT NULL DEFAULT '' COMMENT '权限字符',
  `pmod` varchar(255) DEFAULT NULL COMMENT '模式',
  `name` varchar(255) NOT NULL COMMENT '名称',
  `description` varchar(255) DEFAULT NULL COMMENT '描述',
  `pid` bigint(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB
  • 测试数据

  • 实体类

public class Permission implements GrantedAuthority ,Serializable {

    private static final long serialVersionUID = 1L;

    /**
    * id
    */
    private Long id;

    /**
    * url
    */
    private String url;
    /**
     * name
     */
    private String permission;

    private String pmod;
    /**
    * name
    */
    private String name;

    /**
    * description
    */
    private String description;

    /**
    * pid
    */
    private Long pid;


    public Permission() {
    }

    public Permission(String url) {
        this.url=url;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        if(!url.startsWith("/")){
            url="/"+url;
        }
        this.url = url.trim().replaceAll(" ","");
    }

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Permission that = (Permission) o;
        return url.equals(that.url);
    }

    @Override
    public int hashCode() {
        return Objects.hash(url);
    }

    @Override
    public String toString() {
        return "Permission{" +
                "id=" + id +
                ", url='" + url + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                '}';
    }

    @Override
    @JsonIgnore
    public String getAuthority() {
        return permission;
    }

    public String getPmod() {
        return pmod;
    }

    public void setPmod(String pmod) {
        this.pmod = pmod;
    }
}
  • 实现PermissionEvaluator接口

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {


    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        User user= (User) authentication.getPrincipal();
        PathMatcher pathMatcher = new AntPathMatcher();

        List<Permission> permissions = user.getPermissions();
        for(Permission permission1:permissions){

            if(pathMatcher.match(targetDomainObject.toString(),permission1.getUrl()) && !"".equals(permission1.getPmod())){
                List<String> pmods = Arrays.asList(permission1.getPmod().trim().split(","));
                List<String> perPmods = Arrays.asList(permission.toString().trim().split(","));
                for(String perPmod:perPmods){
                    if(pmods.contains(perPmod))
                        return true;
                }
            }
        }

        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return true;
    }
}
  • 配置

@Configuration
@EnableWebSecurity
//开启授权注解支持
//secured-annotations="enabled"   :springSecurity内部的权限控制注解开关
//pre-post-annotations="enabled"  :spring指定的权限控制注解开关
//jsr250-annotations="enabled"    :jave jsr250注解开关
@EnableGlobalMethodSecurity(prePostEnabled=true,securedEnabled = true,jsr250Enabled = true)
public class MainConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private JWTConfigEntity jwtConfigEntity;

    @Autowired
    private CustomPermissionEvaluator customPermissionEvaluator;

    private ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry;

    @Bean
    public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler(){
        DefaultWebSecurityExpressionHandler handler=new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(customPermissionEvaluator);
        return handler;
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/login").permitAll()
//                .antMatchers("/user/**").hasAnyRole("USER","ADMIN")//需要权限的url
                .anyRequest().authenticated()//其他访问需要验证通过才能访问
                .and()
                .addFilter(new JWTLoginFilter(authenticationManager(),jwtConfigEntity))
                .addFilter(new JWTVerifyFilter(authenticationManager(),jwtConfigEntity,userService,permissionService))
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//禁用session

    }

    /**
     * 忽略拦截url或静态资源文件夹 -
     * web.ignoring(): 会直接过滤该url - 将不会经过Spring Security过滤器链
     * http.permitAll(): 不会绕开springsecurity验证,相当于是允许该路径通过
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.GET,
                "admin/**",
                "/favicon.ico",
                "/*.html",
                "/**/*.css",
                "/**/*.js");
    }
}
  • 在类上使用注解

@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Resource
    private UserService userService;

    /**
     * 因为在springmvc-servlet.xml中开启权限控制的注解支持,所以controller层可以进行授权
     * 以下三种注解都已测试,功能正常
     * @param id
     * @return
     */
//    @Secured({"ROLE_ADMIN"})//springSecurity内部的权限控制注解
//    @RolesAllowed({"ROLE_ADMIN"}) //jsr250注解
    @PreAuthorize("hasRole('ROLE_USER')")//spring指定的权限控制注解:角色
    @RequestMapping("/load")
    public ReturnT<User> load(int id){
        return userService.load(id);
    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")//spring指定的权限控制注解:角色
    @RequestMapping("/load2")
    public ReturnT<User> load2(int id){
        return userService.load(id);
    }

    @PreAuthorize("hasAuthority('user:list')")//spring指定的权限控制注解:权限码
    @RequestMapping("/load3")
    public ReturnT<User> load3(int id){
        return userService.load(id);
    }
    @PreAuthorize("hasAuthority('user:write')")//spring指定的权限控制注解:权限码
    @RequestMapping("/load4")
    public ReturnT<User> load4(int id){
        return userService.load(id);
    }

    @PreAuthorize("hasPermission('/user/load5','r')")//spring指定的权限控制注解:对路径/user/load5拥有"r"权限
    @RequestMapping("/load5")
    public ReturnT<User> load5(int id){
        return userService.load(id);
    }

    @PreAuthorize("hasPermission('/user/*','r')")//spring指定的权限控制注解:路径匹配,对路径/user/*拥有"r"权限
    @RequestMapping("/load6")
    public ReturnT<User> load6(int id){
        return userService.load(id);
    }
    @PreAuthorize("hasPermission('/user/*','r,w')")//spring指定的权限控制注解:路径匹配,对路径/user/*拥有"r,w"权限
    @RequestMapping("/load7")
    public ReturnT<User> load7(int id){
        return userService.load(id);
    }
    @PreAuthorize("hasPermission('/user/*','x,y')")//spring指定的权限控制注解:路径匹配,对路径/user/*拥有"x,y"权限
    @RequestMapping("/load8")
    public ReturnT<User> load8(int id){
        return userService.load(id);
    }
    @PreAuthorize("hasPermission('targetId','targetType','r,w')")//spring指定的权限控制注解:路径匹配
    @RequestMapping("/load9")
    public ReturnT<User> load9(int id){
        return userService.load(id);
    }

}
  • 依次测试:

测试用户:user

角色:ROLE_USER

权限信息:










 


DEMO链接: https://pan.baidu.com/s/1JsEYhqt_PDB5NUWABw9tFQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值