基于用户角色的细粒度validate

7 篇文章 0 订阅
5 篇文章 0 订阅
今天群里小伙伴有个需求,希望通过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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值