基于url的动态权限

方案一:扩展access()的SpEL表达式

.anyRequest().access("@authService.canAcess(request,authentication)")

方案二:自定义AccessDecisionManager

(1)自定义SecurityMetadataSource,实现从数据库加载ConfigAttribute

(2)自定义accessDecisionManager,进行权限校验

(3)使用withObjectPostProcessor,自定义SecurityMetadataSource和accessDecisionManager

方案三:自定义Filter

spring security本来就是由很多的Filter构成的,那么我们可以自定义Filter然后添加到fiterChain中

(1)需要提供认证数据规则数据源数据:通过实现接口FilterInvocationSecurityMetadataSource来进行实现。

(2)自定义accessDecisionManager:进行权限校验

(3)自定义一个拦截器然后把它添加到spring security的fiterChain

这里使用方案一。

一、创建实体类Permission

@Entity
public class Permission {
    @Id @GeneratedValue
    private long id; // 主键

    private  String name; // 权限名称

    private String description; // 权限名称

    /**
     * 注意:Permission表的ulr通配符为两颗星,比如/user下的所有url,应该写成/user/**
     */
    private String url; // 授权连接

    private Long pid; // 父节点

    // 角色 - 权限是多对多的关系
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "RolePermission",joinColumns = {@JoinColumn(name="permission_id")},inverseJoinColumns = {@JoinColumn(name="role_id")})
    private List<Role> roles;

    public long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getDescription() {
        return description;
    }

二、建立RoleRepository

public interface RoleRepository extends JpaRepository<Role,Long> {
}

三、创建service类

public interface PermissionService {
    Map<String, Collection<ConfigAttribute>> getPermissionMap ();
}

@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionRepository permissionRepository;

    private Map<String, Collection<ConfigAttribute>> permissionMap = null;

    @PostConstruct
    /**
     * 从数据库中获取所有权限信息,然后进行遍历,存储到permissionMap集合中
     */
    public void initPermissions() {
        permissionMap = new HashMap<>();
        List<Permission> permissions = permissionRepository.findAll();
        for (Permission p : permissions) {
            Collection<ConfigAttribute> collection = new ArrayList<ConfigAttribute>();
            for (Role role : p.getRoles()) {
                ConfigAttribute configAttribute = new SecurityConfig("ROLE_"+role.getName());
                collection.add(configAttribute);
            }
            permissionMap.put(p.getUrl(),collection);
        }
        System.out.println(permissionMap);
    }

    @Override
    public Map<String,Collection<ConfigAttribute>> getPermissionMap (){
        if(permissionMap == null || permissionMap.size() == 0){
            initPermissions();
        }
        return permissionMap;
    }
}

四、初始化数据

@Service
public class DataInit {
    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private PermissionRepository permissionRepository;

    @PostConstruct
    public void dataInit(){
        // role
        List<Role> roles = new ArrayList<>();
        Role adminRole = new Role();
        adminRole.setName("admin");
        adminRole.setDescprtion("管理员");
        roleRepository.save(adminRole);
        roles.add(adminRole);

        Role userRole = new Role();
        userRole.setName("normal");
        userRole.setDescprtion("普通用户");
        roleRepository.save(userRole);
        roles.add(userRole);

        Permission userPermission = new Permission();
        userPermission.setName("普通用户的url");
        userPermission.setDescription("允许普通用户访问");
        userPermission.setUrl("/hello/helloUser");
        userPermission.setRoles(roles);
        permissionRepository.save(userPermission);

        Permission adminPermission = new Permission();
        adminPermission.setName("管理员的url");
        adminPermission.setDescription("允许管理员访问");
        adminPermission.setUrl("/hello/helloAdmin");
        roles = new ArrayList<>();
        roles.add(adminRole);
        adminPermission.setRoles(roles);
        permissionRepository.save(adminPermission);

        // admin
        UserInfo admin = new UserInfo();
        admin.setUsername("admin");
        admin.setPassword(passwordEncoder.encode("123"));
        admin.setRoles(roles);
        userInfoRepository.save(admin);

        // user
        roles = new ArrayList<>();
        roles.add(userRole);
        UserInfo user = new UserInfo();
        user.setUsername("user");
        user.setPassword(passwordEncoder.encode("123"));
        user.setRoles(roles);
        userInfoRepository.save(user);
    }
}

五、基于url动态获取权限并匹配

@Service
public class AuthService {
    @Autowired
    private PermissionService permissionService;
    public boolean canAcess(HttpServletRequest request, Authentication authentication) {
        boolean b = false;

        String url = request.getRequestURI();

        /**
         * 1、未登录的情况下,需要坐一个判断或者是拦截。
         */Object principal = authentication.getPrincipal();
        if(principal == null || "anonymousUser".equals(principal)) {
          return b;
        }

        /**
         * 2、匿名的角色ROLE_ANONYMOUS
         */
         if(authentication instanceof AnonymousAuthenticationToken) {
             // 匿名角色
             // check
             // return
         }

        /**
         * 3、通过requst对象url,获取到权限信息
         */
        Map<String, Collection<ConfigAttribute>> map = permissionService.getPermissionMap();
        Collection<ConfigAttribute>  configAttributes = null;
        for (Iterator<String> it = map.keySet().iterator();it.hasNext();) {
            String curUrl = it.next();
            AntPathRequestMatcher matcher = new AntPathRequestMatcher(curUrl);
            if (matcher.matches((request))) {
                configAttributes = map.get(curUrl);
                break;
            }
        }

        if(configAttributes == null || configAttributes.size() == 0) {
            return b;
        }

        /**
         * 4、将获取到的权限信息和当前的登陆账号的权限信息进行对比
         */
        for(Iterator<ConfigAttribute> it = configAttributes.iterator();it.hasNext();){
            ConfigAttribute cfa = it.next();
            String role = cfa.getAttribute();
            for(GrantedAuthority authority : authentication.getAuthorities()){
                if(role.equals(authority.getAuthority())){
                    b = true;
                    break;
                }
            }
        }

        return b;
    }
}

六、使用.anyRequest().access()

@Override
protected void configure (HttpSecurity http) throws Exception{
   http.formLogin().loginPage("/login")
   .and()
   .authorizeRequests()
           .antMatchers("/login").permitAll() //允许所有人可以访问登陆页面
    .antMatchers("/","/index").permitAll()
           .antMatchers("/test/**","/test1/**","/favicon.ico").permitAll()
           .antMatchers("/res/**/*.{js,html}").permitAll()

   .anyRequest().access("@authService.canAcess(request,authentication)")
   .and().sessionManagement().maximumSessions(1);
   //.anyRequest().authenticated();//所有的请求需要在登陆之后才能访问
}

遇到问题: 1、登陆成功后总是现实无权访问,这里先将首页设为所以可见。

.antMatchers("/","/index").permitAll()

2、登陆成功后总是访问/favicon.ico,导致权限无法匹配成功,解决办法是加一个/favicon.ico图片,再在使用的页面调用。还有更好的办法。 https://www.jianshu.com/p/b56e524ba2e8 https://blog.csdn.net/sdjadycsdn/article/details/82621234

转载于:https://my.oschina.net/u/2427561/blog/3101437

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值