基于用户角色的细粒度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 <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2016年8月26日 上午10:42:53 <br/>
 * @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<? extends Payload>[] payload() default { };
	/**
	 * 
	 * values:(角色列表). <br/>
	 * 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 <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * Date: 2016年8月26日 上午10:39:29 <br/>
 * 
 * @author 陈勋
 * @version
 * @since JDK 1.7
 * @see
 */
public class RoleConstraintValidator implements
		ConstraintValidator<Annotation, Object> {

	@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<? extends GrantedAuthority> 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 <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2016年8月26日 下午12:59:12 <br/>
 * @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 <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2016年8月26日 下午1:04:18 <br/>
 * @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 <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2016年8月26日 下午1:37:41 <br/>
 * @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 <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON(可选). <br/>
 * date: 2016年8月26日 下午12:58:23 <br/>
 *
 * @author 陈勋
 * @version 
 * @since JDK 1.7
 */
@RestController
public class ProdudctController {
	
	@PostMapping("/product")
	public ResponseEntity<String> product(@Valid  @RequestBody Product product,BindingResult result){
		if(result.hasErrors()){
			return ResponseEntity.ok(result.getFieldError().getDefaultMessage());
		}
		return ResponseEntity.ok("SUCCESS");
	}
	
	
	
	

}


  页面测试
 <!DOCTYPE html>
<html >

<head>
<meta charset="utf-8">
<title>index</title>
<script type="text/javascript" src="jquery.min.js"></script>
</head>
<body >
    <h1>Hello world</h1>
    
    <input type="button" value="testRoleUser" id="add1">
     <input type="button" value="testRoleAdmin" id="add2">
     
     
     <a href="/logout">重新登陆</a>

	<script type="text/javascript">
		$(function(){
			
			$("#add1").on("click",function(){
				
				var values={
	    				name:"abc",
	    				password:"pass"
	    		}
				
				 $.ajax({
		    			url:"product",
		    			type:"post",
		    			contentType:"application/json",
		    			data:JSON.stringify(values) ,		    			
		    			success:function(res){
		    				alert(res);
		    			}
		    		}); 
			});
			
			$("#add2").on("click",function(){
				
				var values={
	    				name:"abc",
	    				desc:"pass"
	    		}
				
				 $.ajax({
		    			url:"product",
		    			type:"post",
		    			contentType:"application/json",
		    			data:JSON.stringify(values) ,		    			
		    			success:function(res){
		    				alert(res);
		    			}
		    		}); 
			});
    		
		});
	
	</script>
</body>
</html>



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