如何为控制器中的许多方法添加权限检查? (过滤器,动作)
How do I add a permission check for many methods in a controller? (Filter, Action)
我很多方法的开头都是下面的
if ((user.privilege & User.Privilege.WRITE) == 0) {
session.setAttribute("alert", "You do not have permission to save.");
return new ModelAndView("redirect:/admin/home");
}
我如何提取它并将其放入一个单独的方法中,该方法在许多其他控制器方法之前被调用,类似于 Ruby on Rails before_action :validate_privilege, [:save, :weekly_report, ...]
?
我在文档中找到了这个,但没有给出任何示例。
我根据@Deadpool 的回答找到了一种方法。它似乎比简单的注释更复杂。
@Bean
public GenericFilterBean beforeAction() {
String[] actions = new String[]{"/admin/censor", "/admin/weekly-report", "/admin/email-blast-submit"};
return new GenericFilterBean() {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// System.out.println("requestURI:"+req.getRequestURI());
boolean found = Arrays.stream(actions).anyMatch(req.getRequestURI()::equals);
if (found) {
User user = (User) req.getSession().getAttribute("user");
if (user != null && (user.privilege & User.Privilege.WRITE) == 0) {
req.getSession().setAttribute("alert", "You do not have permission to save.");
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect("/admin/home");
return;
}
}
chain.doFilter(request, response);
}
};
}
对于使用 OAuth2 的API,我使用了
@Override
public ResponseEntity<...> delete(Principal principal, @RequestBody ...) throws ApiException {
isAuthorized(principal, "ROLE_USER");
...
/** If not authorized, throw ApiException. */
private void isAuthorized(Principal principal, String role) throws ApiException {
OauthClientDetail cd = userMapper.getOauthClientDetails(principal.getName());
if (cd == null || cd.authorities == null || !cd.authorities.equals(role)) {
throw new ApiException(HttpStatus.UNAUTHORIZED, ...);
}
}
(ApiException、OauthClientDetail (POJO) 和 UserMapper (MyBatis) 是自定义的 类。)
如果您正在寻找 Filter
检查每个授权请求,您可以使用 Filter
@Component
public class AuthFilter implements Filter {
@Override
public void doFilter
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
LOG.info(
"Starting a transaction for req : {}",
req.getRequestURI());
chain.doFilter(request, response);
LOG.info(
"Committing a transaction for req : {}",
req.getRequestURI());
}
// other methods
}
public class CustomFilter extends GenericFilterBean {
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
}
您应该使用 Spring 安全性
http.regexMatcher("/*") --> your base path or sth.
.exceptionHandling()
.and()
.csrf()
.disable();
http.addFilterAfter(authenticationProcessingFilter(),BasicAuthenticationFilter.class);
我很多方法的开头都是下面的
if ((user.privilege & User.Privilege.WRITE) == 0) {
session.setAttribute("alert", "You do not have permission to save.");
return new ModelAndView("redirect:/admin/home");
}
我如何提取它并将其放入一个单独的方法中,该方法在许多其他控制器方法之前被调用,类似于 Ruby on Rails before_action :validate_privilege, [:save, :weekly_report, ...]
?
我在文档中找到了这个,但没有给出任何示例。
我根据@Deadpool 的回答找到了一种方法。它似乎比简单的注释更复杂。
@Bean
public GenericFilterBean beforeAction() {
String[] actions = new String[]{"/admin/censor", "/admin/weekly-report", "/admin/email-blast-submit"};
return new GenericFilterBean() {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// System.out.println("requestURI:"+req.getRequestURI());
boolean found = Arrays.stream(actions).anyMatch(req.getRequestURI()::equals);
if (found) {
User user = (User) req.getSession().getAttribute("user");
if (user != null && (user.privilege & User.Privilege.WRITE) == 0) {
req.getSession().setAttribute("alert", "You do not have permission to save.");
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect("/admin/home");
return;
}
}
chain.doFilter(request, response);
}
};
}
对于使用 OAuth2 的API,我使用了
@Override
public ResponseEntity<...> delete(Principal principal, @RequestBody ...) throws ApiException {
isAuthorized(principal, "ROLE_USER");
...
/** If not authorized, throw ApiException. */
private void isAuthorized(Principal principal, String role) throws ApiException {
OauthClientDetail cd = userMapper.getOauthClientDetails(principal.getName());
if (cd == null || cd.authorities == null || !cd.authorities.equals(role)) {
throw new ApiException(HttpStatus.UNAUTHORIZED, ...);
}
}
(ApiException、OauthClientDetail (POJO) 和 UserMapper (MyBatis) 是自定义的 类。)
如果您正在寻找 Filter
检查每个授权请求,您可以使用 Filter
@Component
public class AuthFilter implements Filter {
@Override
public void doFilter
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
LOG.info(
"Starting a transaction for req : {}",
req.getRequestURI());
chain.doFilter(request, response);
LOG.info(
"Committing a transaction for req : {}",
req.getRequestURI());
}
// other methods
}
public class CustomFilter extends GenericFilterBean {
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
}
您应该使用 Spring 安全性
http.regexMatcher("/*") --> your base path or sth.
.exceptionHandling()
.and()
.csrf()
.disable();
http.addFilterAfter(authenticationProcessingFilter(),BasicAuthenticationFilter.class);