今天群里小伙伴有个需求,希望通过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>