如何为 Spring RESTful Web 服务创建 Spring 拦截器
How to create a Spring Interceptor for Spring RESTful web services
我有一些 Spring RESTful (RestControllers) 没有 web.xml 的网络服务,我正在使用 Spring 启动来启动这些服务。
我想为 Web 服务添加授权层,并希望在实际调用 Web 服务本身之前将所有 http 请求路由到一个前端控制器。 (我有一个代码可以在授权层模拟会话行为,根据我从客户端发送的每个 httpRequest 生成的密钥来验证用户)。
是否有关于将所有请求路由到过滤器/前端控制器的标准 Spring 解决方案?
提前致谢,
普拉尼思
编辑:
添加我的代码
控制器:
`
@RestController
public class UserService {
UserDAO userDAO = new UserDAO();
@RequestMapping(value="/login", method = RequestMethod.POST)
@LoginRequired
public String login(@RequestParam(value="user_name") String userName, @RequestParam(value="password") String password, HttpServletRequest request){
return userDAO.login(userName, password);
}
}`
拦截器:
`
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("In Interceptor");
//return super.preHandle(request, response, handler);
return true;
}
@Override
public void postHandle( HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("---method executed---");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("---Request Completed---");
}
}
`
接口。
`
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}
`
这里是一个拦截器的例子:
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
LoginRequired loginRequired = handlerMethod.getMethod().getAnnotation(LoginRequired.class);
if (loginRequired == null) {
return true;
}
String token = httpServletRequest.getParameter("token");
if (StringUtils.isBlank(token)) {
throw new MissingParameterException();
}
authenticationService.checkToken(token);
return super.preHandle(httpServletRequest, httpServletResponse, handler);
}
@Override
public void postHandle( HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("---method executed---");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("---Request Completed---");
}
我们可以创建注释:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}
然后在控制器上,我们有这个注释:
@RequestMapping(value = "/protected/controller")
@LoginRequired
public ResponseEntity<BaseResponse> controller() {
...
}
这只是 template/example 给你一个想法。
希望对您有所帮助。
你应该添加这个来注册你的拦截器
@Configuration
public class MyConfiguration extends WebMvcConfigurerAdapter {
@Bean
AuthenticationInterceptor getAuthenticationInterceptor() {
return new AuthenticationInterceptor();
}
@Override
public void addInterceptors (InterceptorRegistry registry) {
registry.addInterceptor(getAuthenticationInterceptor());
}
}
可以采取以下步骤来实现带有 Spring 的拦截器:
实现拦截器 class 扩展 HandlerInterceptorAdapter class。以下是代码的样子:
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
String emailAddress = request.getParameter("emailaddress");
String password = request.getParameter("password");
if(StringUtils.isEmpty(emailAddress) || StringUtils.containsWhitespace(emailAddress) ||
StringUtils.isEmpty(password) || StringUtils.containsWhitespace(password)) {
throw new Exception("Invalid User Id or Password. Please try again.");
}
return true;
}
}
实施 AppConfig class 或在现有配置之一中添加 addInterceptors class。请注意使用 LoginInterceptor 实例指定的路径模式
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/account/login");
}
}
实现如下控制器方法:
@Controller
@RequestMapping("/account/login")
public class LoginController {
@RequestMapping(method = RequestMethod.GET)
public String login() {
return "login";
}
}
这种事情有一个默认的解决方案。
spring 安全。你只需要实现类似的东西:
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.usernameParameter("email")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
}
它的依赖是:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Spring 5 之后:
实现应该是这样的:我们应该有一个实现
的 class
HandlerInterceptor
public class CustomInterceptor implements HandlerInterceptorr{
}
然后我们可以通过实现WebMvcConfigurer的class注册这个拦截器
并覆盖方法 addInterceptors
public class ServiceInterceptorAppConfig implements WebMvcConfigurer {
@Autowired
CustomInterceptor customInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor);
}
}
如果您正在寻找 spring 启动应用程序的简单答案..
public class HttpInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// do something here.
return true;
}
}
和
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HttpInterceptor());
// registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/account/login"); you can add specific end point as well.
}
}
我有一些 Spring RESTful (RestControllers) 没有 web.xml 的网络服务,我正在使用 Spring 启动来启动这些服务。
我想为 Web 服务添加授权层,并希望在实际调用 Web 服务本身之前将所有 http 请求路由到一个前端控制器。 (我有一个代码可以在授权层模拟会话行为,根据我从客户端发送的每个 httpRequest 生成的密钥来验证用户)。
是否有关于将所有请求路由到过滤器/前端控制器的标准 Spring 解决方案?
提前致谢, 普拉尼思
编辑: 添加我的代码
控制器: `
@RestController
public class UserService {
UserDAO userDAO = new UserDAO();
@RequestMapping(value="/login", method = RequestMethod.POST)
@LoginRequired
public String login(@RequestParam(value="user_name") String userName, @RequestParam(value="password") String password, HttpServletRequest request){
return userDAO.login(userName, password);
}
}`
拦截器:
`
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("In Interceptor");
//return super.preHandle(request, response, handler);
return true;
}
@Override
public void postHandle( HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("---method executed---");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("---Request Completed---");
}
}
`
接口。 `
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}
`
这里是一个拦截器的例子:
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
LoginRequired loginRequired = handlerMethod.getMethod().getAnnotation(LoginRequired.class);
if (loginRequired == null) {
return true;
}
String token = httpServletRequest.getParameter("token");
if (StringUtils.isBlank(token)) {
throw new MissingParameterException();
}
authenticationService.checkToken(token);
return super.preHandle(httpServletRequest, httpServletResponse, handler);
}
@Override
public void postHandle( HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("---method executed---");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("---Request Completed---");
}
我们可以创建注释:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}
然后在控制器上,我们有这个注释:
@RequestMapping(value = "/protected/controller")
@LoginRequired
public ResponseEntity<BaseResponse> controller() {
...
}
这只是 template/example 给你一个想法。 希望对您有所帮助。
你应该添加这个来注册你的拦截器
@Configuration
public class MyConfiguration extends WebMvcConfigurerAdapter {
@Bean
AuthenticationInterceptor getAuthenticationInterceptor() {
return new AuthenticationInterceptor();
}
@Override
public void addInterceptors (InterceptorRegistry registry) {
registry.addInterceptor(getAuthenticationInterceptor());
}
}
可以采取以下步骤来实现带有 Spring 的拦截器:
实现拦截器 class 扩展 HandlerInterceptorAdapter class。以下是代码的样子:
public class LoginInterceptor extends HandlerInterceptorAdapter { @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception { // TODO Auto-generated method stub } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod handlerMethod = (HandlerMethod) handler; String emailAddress = request.getParameter("emailaddress"); String password = request.getParameter("password"); if(StringUtils.isEmpty(emailAddress) || StringUtils.containsWhitespace(emailAddress) || StringUtils.isEmpty(password) || StringUtils.containsWhitespace(password)) { throw new Exception("Invalid User Id or Password. Please try again."); } return true; } }
实施 AppConfig class 或在现有配置之一中添加 addInterceptors class。请注意使用 LoginInterceptor 实例指定的路径模式
@Configuration public class AppConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/account/login"); } }
实现如下控制器方法:
@Controller @RequestMapping("/account/login") public class LoginController { @RequestMapping(method = RequestMethod.GET) public String login() { return "login"; } }
这种事情有一个默认的解决方案。 spring 安全。你只需要实现类似的东西:
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.usernameParameter("email")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
}
它的依赖是:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Spring 5 之后: 实现应该是这样的:我们应该有一个实现
的 classHandlerInterceptor
public class CustomInterceptor implements HandlerInterceptorr{
}
然后我们可以通过实现WebMvcConfigurer的class注册这个拦截器 并覆盖方法 addInterceptors
public class ServiceInterceptorAppConfig implements WebMvcConfigurer {
@Autowired
CustomInterceptor customInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor);
}
}
如果您正在寻找 spring 启动应用程序的简单答案..
public class HttpInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// do something here.
return true;
}
}
和
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HttpInterceptor());
// registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/account/login"); you can add specific end point as well.
}
}