基于用户角色的细粒度validate

阅读更多
  今天群里小伙伴有个需求,希望通过role来控制pojo字段校验。采用方式为spirng securtity+
spring validate 实现
  spring4.0+ 默认支持jsr303。spring validate 也支持自定义valdiate注解。因此采用自定义validate注解实现
代码地址:https://github.com/ChenXun1989/role-validate
自定义validate注解
  /**
 * Project Name:chenxun-cros
 * File Name:RoleConstraint.java
 * Package Name:com.chenxun.validate
 * Date:2016年8月26日上午10:42:53
 * Copyright (c) 2016, www midaigroup com Technology Co., Ltd. All Rights Reserved.
 *
*/

package com.chenxun.example.validate;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.NotNull;

/**
 * ClassName:RoleConstraint 
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2016年8月26日 上午10:42:53
* @author 陈勋 * @version * @since JDK 1.7 * @see */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=RoleConstraintValidator.class) public @interface RoleConstraint { String message() default "ACCESS DENIED !"; Class[] groups() default { }; Class[] payload() default { }; /** * * values:(角色列表).
* ROLE_ADMIN,ROLE_USER * @author 陈勋 * @return * @since JDK 1.7 */ String[] value(); }

  实现constraintValidator 接口
  /**
 * Project Name:chenxun-cros
 * File Name:RoleConstraintValidator.java
 * Package Name:com.chenxun.validate
 * Date:2016年8月26日上午10:39:29
 * Copyright (c) 2016, www midaigroup com Technology Co., Ltd. All Rights Reserved.
 *
 */

package com.chenxun.example.validate;

import java.lang.annotation.Annotation;
import java.util.Collection;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 * ClassName:RoleConstraintValidator 
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2016年8月26日 上午10:39:29
* * @author 陈勋 * @version * @since JDK 1.7 * @see */ public class RoleConstraintValidator implements ConstraintValidator { @Override public void initialize(Annotation constraintAnnotation) { // 初始化动作 可以提升性能。缓存用户的 所有字段。 优化下个方法调用 } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { //默认值处理 if (value == null) { return true; } if (value instanceof Number) { Number num = (Number) value; if (num.byteValue() == 0) { return true; } } // 获取当前用户的角色列表 ConstraintValidatorContextImpl cvci = (ConstraintValidatorContextImpl) context; RoleConstraint rc = (RoleConstraint) cvci.getConstraintDescriptor() .getAnnotation(); String[] roles = rc.value(); // 执行相关逻辑 角色和资源的关系(是否拥有资源权限) // 注意该校验与 value值无关 Collection auths = SecurityContextHolder .getContext().getAuthentication().getAuthorities(); for (GrantedAuthority auth : auths) { // 简单原则,有其中一个角色即可 for (String role : roles) { if (role.equals(auth.getAuthority())) { return true; } } } return false; } }

  表单对象
/**
 * Project Name:validate-role
 * File Name:Product.java
 * Package Name:com.chenxun.example.entity
 * Date:2016年8月26日下午12:59:12
 * Copyright (c) 2016, www midaigroup com Technology Co., Ltd. All Rights Reserved.
 *
*/

package com.chenxun.example.entity;

import lombok.Data;

import com.chenxun.example.validate.RoleConstraint;

/**
 * ClassName:Product 
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2016年8月26日 下午12:59:12
* @author 陈勋 * @version * @since JDK 1.7 * @see */ @Data public class Product { private String name; @RoleConstraint("ROLE_USER") private String password; @RoleConstraint("ROLE_ADMIN") private String desc; }

  权限控制
 /**
 * Project Name:validate-role
 * File Name:SecurityConfig.java
 * Package Name:com.chenxun.example.config
 * Date:2016年8月26日下午1:04:18
 * Copyright (c) 2016, www midaigroup com Technology Co., Ltd. All Rights Reserved.
 *
*/

package com.chenxun.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * ClassName:SecurityConfig 
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2016年8月26日 下午1:04:18
* @author 陈勋 * @version * @since JDK 1.7 * @see */ @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin").password("admin").roles("USER","ADMIN") .and().withUser("user").password("user").roles("USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin().defaultSuccessUrl("/index.html"); http.csrf().disable(); http.authorizeRequests().antMatchers("/**").hasRole("USER"); } }

  /**
 * Project Name:validate-role
 * File Name:SecurityWebApplicationInitializer.java
 * Package Name:com.chenxun.example.config
 * Date:2016年8月26日下午1:37:41
 * Copyright (c) 2016, www midaigroup com Technology Co., Ltd. All Rights Reserved.
 *
*/

package com.chenxun.example.config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

/**
 * ClassName:SecurityWebApplicationInitializer 
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2016年8月26日 下午1:37:41
* @author 陈勋 * @version * @since JDK 1.7 * @see */ public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer{ }

  controler配置
package com.chenxun.example.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;

import com.chenxun.example.entity.Product;

/**
 * 
 * ClassName: ProdudctController 
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON(可选).
* date: 2016年8月26日 下午12:58:23
* * @author 陈勋 * @version * @since JDK 1.7 */ @RestController public class ProdudctController { @PostMapping("/product") public ResponseEntity product(@Valid @RequestBody Product product,BindingResult result){ if(result.hasErrors()){ return ResponseEntity.ok(result.getFieldError().getDefaultMessage()); } return ResponseEntity.ok("SUCCESS"); } }

  页面测试
 




index



    

Hello world

重新登陆


你可能感兴趣的:(java,spring,security,springboot)