package me.test;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyController {
private Logger logger = LoggerFactory.getLogger(MyController.class);
// 示例:通过注解在方法入口处进行权限控制
@RequestMapping("/appointment1")
@PreAuthorize("hasRole('XROLE_READ_APPOINTMENT')")
// 这些权限控制的注解也可以应用到接口上
public String appointment1() {
logger.debug("====== MyController#appointment1()");
return "appointment";
}
@RequestMapping("/staff1")
@PreAuthorize("hasRole('XROLE_READ_STAFF')")
public String staff1() {
logger.debug("====== MyController#staff1()");
return "staff";
}
// 示例:通过编码方式进行权限控制
@RequestMapping("/appointment2")
public String appointment2() {
logger.debug("====== MyController#appointment2()");
SecurityContext secContext = SecurityContextHolder.getContext();
Authentication auth = secContext.getAuthentication();
// 有权限
if (auth.getAuthorities().contains(new SimpleGrantedAuthority("XROLE_READ_APPOINTMENT"))) {
return "appointment";
}
// 没有权限:可以根据业务需要进行相应的动作,而不必是抛出异常。
String msg = null;
throw new AccessDeniedException(msg);
}
@RequestMapping("/staff2")
public String staff2() {
logger.debug("====== MyController#staff2()");
SecurityContext secContext = SecurityContextHolder.getContext();
Authentication auth = secContext.getAuthentication();
// 有权限
if (auth.getAuthorities().contains(new SimpleGrantedAuthority("XROLE_READ_STAFF"))) {
return "staff";
}
// 没有权限:可以根据业务需要进行相应的动作,而不必是抛出异常。
String msg = null;
throw new AccessDeniedException(msg);
}
// 示例:即使没有 XROLE_READ_STAFF 权限,也能通过有权限的入口调用相关代码。
// 即:权限控制只发生类外部类调用当前类的时候,如果同一个类的方法之间相互调用则不会。
@RequestMapping("/a")
@PreAuthorize("isAuthenticated()")
public String a() {
b();
logger.debug("====== MyController#a()");
return "console";
}
@RequestMapping("/b")
@PreAuthorize("hasRole('XROLE_READ_STAFF')")
public String b() {
logger.debug("====== MyController#b()");
return "console";
}
// 示例:默认启用了SecurityContextHolderAwareRequestWrapper,
@RequestMapping("/c")
public String c(HttpServletRequest req) {
logger.debug("====== MyController#c()");
logger.debug(getStackTraceString());
logger.debug("HttpServletRequest: class={}, remoteUser={}", req.getClass().toString(), req.getRemoteUser());
if (req.getUserPrincipal() != null) {
logger.debug("UserPrincipal: class={}, toString()={}", req.getUserPrincipal().getClass(), req.getUserPrincipal().toString());
}
logger.debug("isUserInRole(XROLE_READ_APPOINTMENT)= {}", req.isUserInRole("XROLE_READ_APPOINTMENT"));
logger.debug("isUserInRole(XROLE_READ_STAFF)= {}", req.isUserInRole("XROLE_READ_STAFF"));
return "console";
}
private String getStackTraceString() {
StackTraceElement[] list = Thread.currentThread().getStackTrace();
StringBuilder sb = new StringBuilder();
for (StackTraceElement element : list) {
sb.append(element.toString());
sb.append("\n");
}
return sb.toString();
}
}