Saurav Chaurasia 周五,5 月 7 日,下午 5:00(20 小时前)给我
就像我可以通过在 application.properties 中提供路径、方法和资源来使用静态策略执行器一样。但是在实时应用程序中,我们将拥有 N 个角色,我们将拥有 N 个 API,我们将在 KeyCloak 的资源、策略和权限中提供这些 API。将来,如果我们希望将更多角色添加到 keycloak 中,并且将添加具有必要权限的新资源。我们不会回到我们的 springboot 来更改资源和角色的代码。所有的权限检查都应该对 Spring Boot 是动态的,我们该怎么做,请帮帮我。
我目前使用的静态版本适用于少数角色。我们正在向 keyCloak 添加更多角色。
下面是静态代码。
application.properties
server.port = 8090
keycloak.realm=大学
keycloak.auth-server-url=http://localhost:8080/auth
keycloak.ssl-required=外部
keycloak.resource=课程管理
keycloak.bearer-only=true
keycloak.credentials.secret=a5df9621-73c9-4e0e-9d7a-97e9c692a930
keycloak.securityConstraints[0].authRoles[0]=老师
keycloak.securityConstraints[0].authRoles[1]=ta
keycloak.securityConstraints[0].authRoles[2]=学生
keycloak.securityConstraints[0].authRoles[3]=parent
keycloak.securityConstraints[0].securityCollections[0].name=课程管理
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /courses/get/*
#keycloak.policy-enforcer-config.lazy-load-paths=true
keycloak.policy-enforcer-config.paths[0].path=/courses/get/*
keycloak.policy-enforcer-config.paths[0].methods[0].method=GET
keycloak.policy-enforcer-config.paths[0].methods[0].scopes[0]=view
keycloak.policy-enforcer-config.paths[0].methods[1].method=DELETE
keycloak.policy-enforcer-config.paths[0].methods[1].scopes[0]=delete
配置.class
package com.lantana.school.course.coursemanagment.security;
`导入java.util.List;
导入 org.keycloak.AuthorizationContext;
导入 org.keycloak.KeycloakSecurityContext;
导入 org.keycloak.representations.idm.authorization.Permission;
公共类身份{
private final KeycloakSecurityContext securityContext;
public Identity(KeycloakSecurityContext securityContext) {
this.securityContext = securityContext;
}
/**
* An example on how you can use the {@link org.keycloak.AuthorizationContext} to check for permissions granted by Keycloak for a particular user.
*
* @param name the name of the resource
* @return true if user has was granted with a permission for the given resource. Otherwise, false.
*/
public boolean hasResourcePermission(String name) {
System.out.println("Permission: "+getAuthorizationContext().hasResourcePermission(name));
return getAuthorizationContext().hasResourcePermission(name);
}
/**
* An example on how you can use {@link KeycloakSecurityContext} to obtain information about user's identity.
*
* @return the user name
*/
public String getName() {
System.out.println("UserName: "+securityContext.getIdToken().getPreferredUsername());
return securityContext.getIdToken().getPreferredUsername();
}
/**
* An example on how you can use the {@link org.keycloak.AuthorizationContext} to obtain all permissions granted for a particular user.
*
* @return
*/
public List<Permission> getPermissions() {
System.out.println("Permission 2: "+getAuthorizationContext().getPermissions());
return getAuthorizationContext().getPermissions();
}
/**
* Returns a {@link AuthorizationContext} instance holding all permissions granted for an user. The instance is build based on
* the permissions returned by Keycloak. For this particular application, we use the Entitlement API to obtain permissions for every single
* resource on the server.
*
* @return
*/
private AuthorizationContext getAuthorizationContext() {
System.out.println("getAuthorizationContext: "+ securityContext.getAuthorizationContext());
return securityContext.getAuthorizationContext();
}
}`
控制器类
package com.lantana.school.course.coursemanagment.services;
导入 java.math.BigInteger;
导入 java.net.URI;
导入 java.util.ArrayList;
导入 java.util.List;
导入 javax.servlet.http.HttpServletRequest;
导入 org.keycloak.KeycloakSecurityContext;
导入 org.springframework.beans.factory.annotation.Autowired;
导入 org.springframework.hateoas.EntityModel;
//导入 org.springframework.hateoas.Link;
//导入 org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
//导入 org.springframework.http.HttpHeaders;
导入 org.springframework.http.MediaType;
导入 org.springframework.http.ResponseEntity;
导入 org.springframework.ui.Model;
导入 org.springframework.web.bind.annotation.DeleteMapping;
导入 org.springframework.web.bind.annotation.GetMapping;
导入 org.springframework.web.bind.annotation.PathVariable;
导入 org.springframework.web.bind.annotation.PostMapping;
导入 org.springframework.web.bind.annotation.RequestBody;
导入 org.springframework.web.bind.annotation.RequestHeader;
导入 org.springframework.web.bind.annotation.RestController;
导入 org.springframework.web.servlet.support.ServletUriComponentsBuilder;
导入 com.fasterxml.jackson.core.JsonProcessingException;
导入 com.lantana.school.course.coursemanagment.security.Identity;
@RestController
公共类课程控制器{
@Autowired
private HttpServletRequest request;
@Autowired
private CourseService couseService;
@Autowired
private hateo hatoeslink;
List<String> rol=new ArrayList<String>();
//
// @GetMapping(value = "/courses/api")
// public String generateApi(@RequestHeader("Authorization") String token){
////// rol.clear();
////// 列表头 = 令牌。;
// System.out.println("Token: "+token);
////// System.out.println("角色控制器:"+rol);
////// rol=couseService.getRole(token);
////// List<?> link=new ArrayList<>();
//////
// return new String("Role Fetched");
// }
@GetMapping(value = "/courses/get/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public EntityModel<Course> getCourse(@PathVariable("id") long id, Model model,@RequestHeader("Authorization") String token) throws JsonProcessingException {
configCommonAttributes(model);
rol=couseService.getRole(token);
System.out.println("GetRole: "+rol);
Course course = couseService.getCourse(id);
hatoeslink.hateoLink(rol, id, model, token);
return EntityModel.of(course);
}
@DeleteMapping("/courses/delete/{id}")
public EntityModel<Course> deleteStudent(@PathVariable long id) {
System.out.println("calling delete operation");
//
Course course = couseService.getCourse(id);
couseService.deleteById(id);
return EntityModel.of(course);
}
@PostMapping("/courses")
public ResponseEntity<Course> createCourse(@RequestBody Course course) {
Course savedCourse = couseService.addCourse(course);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(savedCourse.getCode()).toUri();
return ResponseEntity.created(location).build();
}
private void configCommonAttributes(Model model) {
model.addAttribute("identity", new Identity(getKeycloakSecurityContext()));
}
private KeycloakSecurityContext getKeycloakSecurityContext() {
return (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
}
}
服务类
import java.nio.charset.StandardCharsets;
导入 java.util.ArrayList;
//导入java.util.Iterator;
导入 java.util.LinkedHashMap;
导入 java.util.List;
导入 java.util.Map;
导入 org.apache.commons.codec.binary.Base64;
导入 org.json.JSONArray;
导入 org.json.JSONObject;
导入 org.springframework.stereotype.Component;
@零件
公共类 CourseService {
public static final Map<Long, Course> courseMap = new LinkedHashMap<Long, Course>();
static {
Course cs2001 = new Course("CS2001", "Mathematical Foundations of Computing", "introduction", "term1");
Course cs2002 = new Course("CS2002", "Computer Organization and Systems", "introduction", "term1");
Course cs2003 = new Course("CS2003", "Data Management and Data Systems", "introduction", "term2");
Course cs2004 = new Course("CS2004", "Introduction to Computer Graphics and Imaging", "introduction", "term3");
Course cs2005 = new Course("CS2005", "Design and Analysis of Algorithms", "introduction", "term4");
Course cs2006 = new Course("CS2006", "Analysis of Networks", "introduction", "term4");
courseMap.put(cs2001.getId(), cs2001);
courseMap.put(cs2002.getId(), cs2002);
courseMap.put(cs2003.getId(), cs2003);
courseMap.put(cs2004.getId(), cs2004);
courseMap.put(cs2005.getId(), cs2005);
courseMap.put(cs2006.getId(), cs2006);
}
public Course getCourse(Long id) {
return courseMap.get(id);
}
public Course addCourse(Course course) {
courseMap.put(course.getId(), course);
return course;
}
public void deleteById(long id) {
courseMap.remove(id);
// return id+"删除成功";
}
public List<String> getRole(String token) {
String[] payload=token.split("\\.");
byte[] bytes = Base64.decodeBase64(payload[1]);
String decodedString = new String(bytes, StandardCharsets.UTF_8);
// System.out.println("解码:" + decodedString);
JSONObject jo=new JSONObject(decodedString);
JSONObject obj=jo.getJSONObject("realm_access");
JSONArray jArray=obj.getJSONArray("roles");
System.out.println(obj);
System.out.println(jArray);
List<String> role=new ArrayList();
for(int i=0;i<jArray.length();i++)
{ String ro=(String) jArray.get(i);
System.out.println(jArray.get(i));
role.add(ro);
}
// 列表动作=new ArrayList();
// 映射角色=((Map)jo.get("realm_access"));
// Iterator<Map.Entry> itr1=roles.entrySet().iterator();
// while(itr1.hasNext())
// {
// Map.Entry pair=itr1.next();
// System.out.println(pair);
// }
return role;
}
}
模型类
package com.lantana.school.course.coursemanagment.services;
导入 org.springframework.hateoas.RepresentationModel;
公共类课程扩展了RepresentationModel {
private static long nextID = 1000;
public Course(String code, String name, String modules, String enrollmentTerm) {
super();
this.id = nextID++;
this.code = code;
this.name = name;
this.modules = modules;
this.enrollmentTerm = enrollmentTerm;
}
Long id;
String code;
String name;
String modules;
String enrollmentTerm;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getModules() {
return modules;
}
public void setModules(String modules) {
this.modules = modules;
}
public String getEnrollmentTerm() {
return enrollmentTerm;
}
public void setEnrollmentTerm(String enrollmentTerm) {
this.enrollmentTerm = enrollmentTerm;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
hatos 自定义类
package com.lantana.school.course.coursemanagment.services;
导入 java.util.List;
导入 org.springframework.beans.factory.annotation.Autowired;
导入 org.springframework.hateoas.EntityModel;
导入 org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
导入 org.springframework.stereotype.Component;
导入 org.springframework.ui.Model;
导入 com.fasterxml.jackson.core.JsonProcessingException;
@零件
公共课仇恨{
@Autowired
private CourseService couseService;
public EntityModel<Course> hateoLink(List<String> role,long id,Model model,String token)
{ Course course = couseService.getCourse(id);
course.removeLinks();
role.stream().forEach(action ->{
if(action.equalsIgnoreCase("teacher"))
{
// course.removeLinks();
course.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(CourseController.class).createCourse(course)).withRel("add"));
}
if(action.equalsIgnoreCase("student"))
{
try {
course.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(CourseController.class).getCourse(id, model,token)).withRel("view"));
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(action.equalsIgnoreCase("parent"))
{
course.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(CourseController.class).deleteStudent(id)).withRel("delete"));
}
});
return EntityModel.of(course);
}
}