首页 > 其他分享 >SpringMVC学习系列(9) 之 实现注解式权限验证

SpringMVC学习系列(9) 之 实现注解式权限验证

时间:2023-05-29 13:02:21浏览次数:48  
标签:web 验证 SpringMVC import action 注解 权限 annotation


对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现。但借助于Spring MVC中的action拦截器我们可以实现注解式的权限验证。

一.首先介绍一下action拦截器:

HandlerInterceptor是Spring MVC为我们提供的拦截器接口,来让我们实现自己的处理逻辑,HandlerInterceptor 的内容如下:




public interface HandlerInterceptor {  
    boolean preHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler)   
            throws Exception;  
  
    void postHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, ModelAndView modelAndView)   
            throws Exception;  
  
    void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, Exception ex)  
            throws Exception;  
}





可以看到接口有3个方法,其含义如下:

preHandle:在执行action里面的处理逻辑之前执行,它返回的是boolean,这里如果我们返回true在接着执行postHandle和afterCompletion,如果我们返回false则中断执行。

postHandle:在执行action里面的逻辑后返回视图之前执行。

afterCompletion:在action返回视图后执行。

HandlerInterceptorAdapter适配器是Spring MVC为了方便我们使用HandlerInterceptor而对HandlerInterceptor 的默认实现,里面的3个方法没有做任何处理,在preHandle方法直接返回true,这样我们继承HandlerInterceptorAdapter后只需要实现3个方法中我们需要的方法即可,而不像继承HandlerInterceptor一样不管是否需要3个方法都要实现。

当然借助于HandlerInterceptor我们可以实现很多其它功能,比如日志记录、请求处理时间分析等,权限验证只是其中之一。

 

二.下面我们就来一步一步来完成注解式权限验证的功能。

首先添加一个账户的Controller和登录的Action及视图来模拟在没有权限时跳转到登陆页面,内容分别如下:

com.demo.web.controllers包中的AccountController.java:




package com.demo.web.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value = "/account")
public class AccountController {
    
    @RequestMapping(value="/login", method = {RequestMethod.GET})
    public String login(){
        
        return "login";
    }
    
}




views文件夹下的视图login.jsp:




<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    这里是登录界面
</body>
</html>




新建包com.demo.web.auth,添加自定义注解AuthPassport,内容如下:




package com.demo.web.auth;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthPassport {
    boolean validate() default true;
}




添加自己的拦截器实现AuthInterceptor继承于HandlerInterceptorAdapter,内容如下:




package com.demo.web.auth;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class AuthInterceptor extends HandlerInterceptorAdapter {
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        if(handler.getClass().isAssignableFrom(HandlerMethod.class)){
            AuthPassport authPassport = ((HandlerMethod) handler).getMethodAnnotation(AuthPassport.class);
            
            //没有声明需要权限,或者声明不验证权限
                if(authPassport == null || authPassport.validate() == false)
                return true;
            else{                
                //在这里实现自己的权限验证逻辑
                if(false)//如果验证成功返回true(这里直接写false来模拟验证失败的处理)
                    return true;
                else//如果验证失败
                {
                    //返回到登录界面
                    response.sendRedirect("account/login");
                    return false;
                }       
            }
        }
        else
            return true;   
     }
}




配置项目的springservlet-config.xml添加如下内容:



<mvc:interceptors>  
    <!-- 国际化操作拦截器 如果采用基于(请求/Session/Cookie)则必需配置 --> 
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />  
    <!-- 如果不定义 mvc:mapping path 将拦截所有的URL请求 -->
    <bean class="com.demo.web.auth.AuthInterceptor"></bean>
</mvc:interceptors>



这样在执行每个action方法是都会调用AuthInterceptor处理,当判断action上有我们定义AuthPassport注解时就会执行里面的权限验证逻辑。

运行项目:

SpringMVC学习系列(9) 之 实现注解式权限验证_spring

可以看到执行了我们在springservlet-config.xml定义的HelloworldController的index方法。



<!-- 如果当前请求为“/”时,则转发到“/helloworld/index" -->
<mvc:view-controller path="/" view-name="forward:/helloworld/index"/>



下面我们在HelloworldController的index方法上加上自定义注解AuthPassport:




@AuthPassport
@RequestMapping(value={"/index","/hello"})
public ModelAndView index(){
    
    ModelAndView modelAndView = new ModelAndView();  
    modelAndView.addObject("message", "Hello World!");  
    modelAndView.setViewName("index");  
    return modelAndView;
}




重新运行项目:

SpringMVC学习系列(9) 之 实现注解式权限验证_测试_02

可以看到正确执行了权限判断逻辑,这样我们只需要在我们在需要权限验证的action上加上这个注解就可以实现权限控制功能了。

 

注解式权限验证的内容到此结束。

 

标签:web,验证,SpringMVC,import,action,注解,权限,annotation
From: https://blog.51cto.com/u_16131764/6370143

相关文章

  • SpringMVC学习系列(8) 之 国际化
    在系列(7)中我们讲了数据的格式化显示,Spring在做格式化展示的时候已经做了国际化处理,那么如何将我们网站的其它内容(如菜单、标题等)做国际化处理呢?这就是本篇要将的内容—>国际化。一.基于浏览器请求的国际化实现:首先配置我们项目的springservlet-config.xml文件添加的内容如下:<bean......
  • SpringMVC学习系列(6) 之 数据验证
    在系列(4)、(5)中我们展示了如何绑定数据,绑定完数据之后如何确保我们得到的数据的正确性?这就是我们本篇要说的内容—>数据验证。这里我们采用Hibernate-validator来进行验证,Hibernate-validator实现了JSR-303验证框架支持注解风格的验证。首先我们要到http://hibernate.org/validator......
  • SpringMVC学习系列(7) 之 格式化显示
    在系列(6)中我们介绍了如何验证提交的数据的正确性,当数据验证通过后就会被我们保存起来。保存的数据会用于以后的展示,这才是保存的价值。那么在展示的时候如何按照要求显示?(比如:小数保留一定的位数,日期按指定的格式等)。这就是本篇要说的内容—>格式化显示。从Spring3.X开始,Spring提供......
  • SpringMVC学习系列(10) 之 异常处理
    在项目中如何处理出现的异常,在每个可能出现异常的地方都写代码捕捉异常?这显然是不合理的,当项目越来越大是也是不可维护的。那么如何保证我们处理异常的代码精简且便于维护呢?这就是本篇要讲的内容—>异常处理。在SpringMVC中我们可以通过以下2中途径来对异常进行集中处理:一.继承Han......
  • 转载:权限鉴定结构
     1.1    权限所有的Authentication实现类都保存了一个GrantedAuthority列表,其表示用户所具有的权限。GrantedAuthority是通过AuthenticationManager设置到Authentication对象中的,然后AccessDecisionManager将从Authentication中获取用户所具有的GrantedAuthority来鉴定用户是......
  • 基于注解的Spring AOP的配置和使用
    AOP是OOP的延续,是AspectOrientedProgramming的缩写,意思是面向切面编程。可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标......
  • 自定义注解时常用注解
    @Target@Target:注解的作用目标@Target(ElementType.TYPE)——接口、类、枚举、注解@Target(ElementType.FIELD)——字段、枚举的常量@Target(ElementType.METHOD)——方法@Target(ElementType.PARAMETER)——方法参数@Target(ElementType.CONSTRUCTOR)——构造函数@Target(Eleme......
  • ABAP 用户权限查询报表
    *&---------------------------------------------------------------------**&REPORTZUSER*&---------------------------------------------------------------------**&*&--------------------------------------------------------------------......
  • Spring6 探析之@Lazy 注解
    Spring6探析之@Lazy注解介绍在实际项目中,如果我们加载了过多的实例或配置,会导致Spring的启动速度非常慢,@Lazy注解就是为了解决这种问题。@Lazy注解采用懒汉模式的单例模式,Spring容器启动时,被标记的实例不会创建,只有在第一次使用时才会创建实例,这样就解决了Spring启动......
  • Spring6 探析之@Conditional 注解
    Spring6探析之@Conditional注解介绍我们写业务逻辑时,会用到if-else条件,@Conditional注解可以通过条件判断是否要将Bean注入到IOC容器中,它可以标记在类和方法上,我们先看一下源码吧@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME......