Spring Security-- springmvc_JSP_mybatis_tomcat整合

  • 工程目录结构:

  • pom

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.zeng</groupId>
  <artifactId>SpringSecurityDemo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>SpringSecurityDemo Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.version>5.1.5.RELEASE</spring.version>
  </properties>

  <dependencies>
    <!--Spring框架核心库 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- Spring MVC -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.2</version>
    </dependency>

    <!-- Spring-Jdbc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!--Spring-test -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- Spring面向切面编程 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!--MyBatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.2</version>
    </dependency>
    <!-- MyBatis整合Spring的适配包 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>

    <!-- 数据库连接池、驱动 -->
    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.41</version>
    </dependency>

    <!-- (jstl,servlet-api,junit) -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-taglibs</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>jsr250-api</artifactId>
      <version>1.0</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>SpringSecurityDemo</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
  • web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>

    <!--
          启动spring容器,并且需要配置Spring的配置文件,这样Spring容器才能够正确的启动
      -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <!--字符编码过滤器配置-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <!--spring security过滤器链,注意过滤器名称必须叫springSecurityFilterChain-->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <!--字符编码过滤器映射-->
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--spring security过滤器链映射-->
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--配置spring监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--SpringMVC拦截所有请求,这样就能把请求交给SpringMVC了,而不再是最初的样子,但本质上还是servlet-->
    <servlet>
        <!--名称 -->
        <servlet-name>springmvc</servlet-name>
        <!-- Servlet类 -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!--SpringMVC配置参数文件的位置 -->
            <param-name>contextConfigLocation</param-name>
            <!--默认名称为ServletName-servlet.xml -->
            <param-value>classpath*:springmvc-servlet.xml</param-value>
        </init-param>
        <!-- 启动顺序,数字越小,启动越早 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--所有请求都会被springmvc拦截 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


    <!--资源找不到:404-->
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>

    <!--异常统一处理方式2-->
    <!--权限不足:403
    <error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>-->
</web-app>
  • spring配置文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--
            此标签用来扫描包以及包下面的类,被扫描到的类就可以使用注解,如@Service等,同时被扫描到后就会被放入IOC容器中,
            之所以不扫描Controller,就是因为Controller是要交给SpringMVC扫描的,后面会看到
        -->
    <context:component-scan base-package="com.zeng">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--这里引入之前创建的jdbc配置文件,这样可以很灵活的改变配置,而不需要修改xml文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置连接池,引入了jdbc.properties以后,就可以很方便的使用配置信息,但是必须要用${}这种形式调用-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
        <property name="user" value="${jdbc.usernaem}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--
            配置mybatis整合开发
            Mybatis首先要有一个数据源,所以我们就将刚刚配置的连接池注入进来
            然后还需要mapper.xml文件的路径,之前学Mybatis的时候都是手动创建**.xml文件,然后用接口去映射,
            好消息是mybatis能够帮助我们根据数据库逆向生成这个文件及接口,极大的方便了我们的开发
            最后就是mybatis的配置文件,我们会在后面看到
            -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <!--
        配置SqlSession
        sqlsession的作用就是sql会话,没有这个mybatis就无法真正作用起来,如果你学过mybatis一定知道这个配置的意义,
        将sqlSessionFactory注入到其中,至于下面那个参数,暂时先不用理解
        -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        <!-- defaultExecutorType设置为BATCH有个缺陷就是无法获取update、delete返回的行数
        <constructor-arg name="executorType" value="BATCH"/>-->
    </bean>

    <!--
            将dao接口实现放入到IOC容器中,由于我们还没有配置mapper的接口文件,所以需要将接口实现文件放入到IOC中,注入的时候就能够直接使用
        -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zeng.dao"/>
    </bean>

    <!--
        事务控制
    -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--控制数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--事务增强-->
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="*"/>
            <!--以get开始的所有方法-->
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>


    <!--开启基于注解的控制,一般使用配置方式进行控制-->
    <aop:config>
        <!--切入点表达式-->
        <aop:pointcut id="txPoint" expression="execution(* com.zeng.service..*(..))"/>
        <!--事务增强配置-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
    </aop:config>

    <!--引入spring security的配置-->
    <import resource="springSecurity-config.xml"/>
</beans>
  • spring security的配置文件

  1. spring security的配置文件可以在spring配置文件中引入,也可以在springMVC中引入。
  2. 开启权限控制的注解支持如果放在springIOC容器中的话,只会对service层起作用,如果放在springMVC里的话,只会对controller层起作用,因为springMVC不会扫描service、dao的包,同理,spring不会扫描controller包
  3. 三种授权方式的开启:

            secured-annotations="enabled"
            pre-post-annotations="enabled"
            jsr250-annotations="enabled"

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">

    <!--
    不需要经过spring security过滤器的url
        logFailure.jsp:登录失败的页面
    -->
    <security:http security="none" pattern="/**/403.jsp"/>
    <security:http security="none" pattern="/**/404.jsp"/>
    <security:http security="none" pattern="/**/500.jsp"/>
    <security:http security="none" pattern="/**/logFailure.jsp"/>

    <bean id="accessDeniedHandler" class="com.zeng.exception.AccessDeniedServletHandler"/>

    <security:http auto-config="true" use-expressions="true">
        <!--
        匿名访问:
            login.jsp:登录页面,国为需要防止csrf过滤器,所以设置为匿名访问
        -->
        <security:intercept-url pattern="/login.jsp" access="permitAll()"/>

        <!--需要权限的url pattern配置-->
        <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>

        <!--
        异常统一处理方式1:
        403认证失败处理
            也可以使用error-page="/403.jsp"属性,但推荐在web.xml中设置:
            <error-page>
                <error-code>403</error-code>
                <location>/403.jsp</location>
            </error-page>
        <security:access-denied-handler ref="accessDeniedHandler" />
        -->

        <!--防止csrf攻击:true为关闭
        <security:csrf disabled="true"/>-->

        <!--
        login-page:自定义登录页面
        default-target-url:登陆成功后跳转的页面
        login-processing-url:登录时提交的处理地址
        -->
        <security:form-login
                login-page="/login.jsp"
                default-target-url="/admin/main"
                login-processing-url="/login"
                authentication-failure-url="/logFailure.jsp"/>

        <!--注销-->
        <security:logout logout-url="/logout" logout-success-url="/login.jsp"/>

        <!--
        启用remember me功能:关闭浏览器后,在指定的时间内可以不用再次输入密码
        data-source-ref="dataSource":指定数据库连接池
        token-validity-seconds="86400":设置token存储时间为24*3600秒
        remember-me-parameter="remember-me":指定记住的参数名
        remember-me-cookie="loginToken":在cookie中保存的key名
        -->
        <security:remember-me
                remember-me-cookie="loginToken"
                token-validity-seconds="86400"
                data-source-ref="dataSource"
                remember-me-parameter="remember-me"/>

    </security:http>

    <!--开启权限控制的注解支持:
        如果此配置放在springIOC容器中的话,只会对service层起作用,
        如果放在springMVC里的话,只会对controller层起作用

        secured-annotations="enabled"   :springSecurity内部的权限控制注解开关
        pre-post-annotations="enabled"  :spring指定的权限控制注解开关
        jsr250-annotations="enabled"    :jave jsr250注解开关
    -->
    <security:global-method-security
            secured-annotations="enabled"
            pre-post-annotations="enabled"
            jsr250-annotations="enabled"/>

    <bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="userServiceImpl">
            <!--Spring security 5.0中新增的多种加密方式,-->
            <security:password-encoder ref="bcryptEncoder"/>
        </security:authentication-provider>

        <!--<security:authentication-provider user-service-ref="userServiceImpl">-->
        <!--<security:user-service>-->
        <!--<security:user name="user" authorities="ROLE_ADMIN" password="{noop}123"/>-->
        <!--</security:user-service>-->
        <!--</security:authentication-provider>-->
    </security:authentication-manager>

</beans>
  • jdbc.properties

# 连接url
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/springSecurity
# 驱动器
jdbc.driverClassName=com.mysql.jdbc.Driver
# 用户名
jdbc.usernaem=root
# 密码
jdbc.password=root
  • mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
</configuration>
  • springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">

    <!--
        SpringMVC的配置文件,包含网站跳转逻辑的控制,配置
    -->

    <!--自动扫描包,实现支持注解的IOC 此时的扫描才是扫描Controller,开启Controller注解 -->
    <context:component-scan base-package="com.zeng.controller" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />

    <!-- 支持mvc注解驱动 能支持springmvc更高级的一些功能,JSR303校验,快捷的ajax...映射动态请求-->
    <mvc:annotation-driven/>

    <!--开启权限控制的注解支持:
        如果此配置放在springIOC容器中的话,只会对service层起作用,
        如果放在springMVC里的话,只会对controller层起作用

        secured-annotations="enabled"   :springSecurity内部的权限控制注解开门
        pre-post-annotations="enabled"  :spring指定的权限控制注解开关
        jsr250-annotations="enabled"    :jave250注解开关
    -->
    <security:global-method-security
            secured-annotations="enabled"
            pre-post-annotations="enabled"
            jsr250-annotations="enabled"/>

    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/view/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>
</beans>
  • UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zeng.dao.UserDao">

    <resultMap id="BaseResultMap" type="com.zeng.entity.User" >
        <result column="id" property="id" />
        <result column="username" property="username" />
        <result column="password" property="password" />
    </resultMap>

    <sql id="Base_Column_List">
                id,
                username,
                password
    </sql>

    <insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id" parameterType="com.zeng.entity.User">
        INSERT INTO user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test ='null != username'>
                username,
            </if>
            <if test ='null != password'>
                password
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test ='null != username'>
                #{username},
            </if>
            <if test ='null != password'>
                #{password}
            </if>
        </trim>
    </insert>

    <delete id="delete" >
        DELETE FROM user
        WHERE id = #{id}
    </delete>

    <update id="update" parameterType="com.zeng.entity.User">
        UPDATE user
        <set>
            <if test ='null != username'>username = #{username},</if>
            <if test ='null != password'>password = #{password}</if>
        </set>
        WHERE id = #{id}
    </update>


    <select id="load" resultMap="BaseResultMap">
        SELECT <include refid="Base_Column_List" />
        FROM user
        WHERE id = #{id}
    </select>
    <select id="findByUsername" resultMap="BaseResultMap">
        SELECT <include refid="Base_Column_List" />
        FROM user
        WHERE username=#{username}
    </select>
    <select id="findRoleByUserId" resultType="string">
        select r.name
        FROM user u
        left JOIN user_role ur
        on u.id=ur.user_id
        LEFT JOIN role r
        on r.id=ur.role_id
        WHERE u.id=#{id}
    </select>

    <select id="pageList" resultMap="BaseResultMap">
        SELECT <include refid="Base_Column_List" />
        FROM user
        LIMIT #{offset}, #{pageSize}
    </select>

    <select id="pageListCount" resultType="java.lang.Integer">
        SELECT count(1)
        FROM user
    </select>

</mapper>
  • 异常处理

  •  在security配置文件中配置:
<security:access-denied-handler ref="accessDeniedHandler" />

 

public class AccessDeniedServletHandler implements AccessDeniedHandler {

    private static final String DEF_ERROR_PAGE_PATH = "/403.jsp";

    @Override

    public void handle(HttpServletRequest request, HttpServletResponse response,

                       AccessDeniedException accessDeniedException) throws IOException, ServletException {

        response.sendRedirect(request.getContextPath()+DEF_ERROR_PAGE_PATH);
    }

}
  •  在web.xml中配置:
<error-page>
    <error-code>403</error-code>
    <location>/403.jsp</location>
</error-page>
  • java配置方式一:
@Component
public class HandlerException implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView mv=new ModelAndView();
        //基本不用,因为不会把错误信息放到页面展示给用户
        mv.addObject("msg", ex.getMessage());
        if(ex instanceof AccessDeniedException){
            mv.setViewName("forward:/403.jsp");
        }else {
            mv.setViewName("redirect:/500.jsp");
        }
        return mv;
    }
}
  • java配置方式二(推荐):

@ControllerAdvice
public class HandlerExceptionAdvice {
    @ExceptionHandler(AccessDeniedException.class)
    public String handler403Exception() {
        return "forward:/403.jsp";
    }

    @ExceptionHandler(RuntimeException.class)
    public String handler500Exception() {
        return "forward:/500.jsp";
    }
}
  • controller层

请注意三种授权方式:

  1. @Secured({"ROLE_ADMIN"})   //springSecurity内部的权限控制注解
  2. @RolesAllowed({"ROLE_ADMIN"}) //jsr250注解
  3. @PreAuthorize("hasRole('ROLE_ADMIN')") //spring指定的权限控制注解
@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Resource
    private UserService userService;

    @RequestMapping("/insert")
    public ReturnT<String> insert(User user){
        return userService.insert(user);
    }

    @RequestMapping("/delete")
    public ReturnT<String> delete(int id){
        return userService.delete(id);
    }

    @RequestMapping("/update")
    public ReturnT<String> update(User user){
        return userService.update(user);
    }

    /**
     * 因为在springmvc-servlet.xml中开启权限控制的注解支持,所以controller层可以进行授权
     * 以下三种注解都已测试,功能正常
     * @param id
     * @return
     */
//    @Secured({"ROLE_ADMIN"})//springSecurity内部的权限控制注解
//    @RolesAllowed({"ROLE_ADMIN"}) //jsr250注解
    @PreAuthorize("hasRole('ROLE_ADMIN')")//spring指定的权限控制注解
    @RequestMapping("/load")
    public ReturnT<User> load(int id){
        return userService.load(id);
    }

    @RequestMapping("/pageList")
    public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int offset,
                                        @RequestParam(required = false, defaultValue = "10") int pagesize) {
        return userService.pageList(offset, pagesize);
    }

}
  • service接口层

因为service接口继承了UserDetailsService接口,所以实现类需要实现loadUserByUsername方法

public interface UserService extends UserDetailsService {

    /**
     * 新增
     */
    public ReturnT<String> insert(User user);

    /**
     * 删除
     */
    public ReturnT<String> delete(int id);

    /**
     * 更新
     */
    public ReturnT<String> update(User user);

    /**
     * 根据主键 id 查询
     */
    public ReturnT<User> load(int id);

    /**
     * 分页查询
     */
    public Map<String,Object> pageList(int offset, int pageSize);

}
@Service
@Transactional
public class UserServiceImpl implements UserService {

	@Resource
	private UserDao userDao;

	@Override
	public ReturnT<String> insert(User user) {

		if (user == null) {
			return new ReturnT<String>(ReturnT.FAILURE_CODE, "必要参数缺失");
        }

		userDao.insert(user);
        return ReturnT.SUCCESS;
	}

	/**
	 * 因为在springSecurity-config.xml中开启权限控制的注解支持(在springIOC中),所以service层和dao层都可以进行授权
	 * @param id
	 * @return
	 */
	@Secured("ROLE_ADMIN")
	@Override
	public ReturnT<String> delete(int id) {
		int ret = userDao.delete(id);
		return ret>0?ReturnT.SUCCESS:ReturnT.FAILURE;
	}

	@Override
	public ReturnT<String> update(User user) {
		int ret = userDao.update(user);
		return ret>0?ReturnT.SUCCESS:ReturnT.FAILURE;
	}

	@Override
	public ReturnT<User> load(int id) {
		User user = userDao.load(id);
		return new ReturnT(user);
	}


	@Override
	public Map<String,Object> pageList(int offset, int pageSize) {

		List<User> pageList = userDao.pageList(offset, pageSize);
		int totalCount = userDao.pageListCount(offset, pageSize);

		// result
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("pageList", pageList);
		result.put("totalCount", totalCount);
		result.put("offset",offset);
		result.put("pageSize",pageSize);

		return result;
	}

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		//通过用户名查找用户
		User user=userDao.findByUsername(username);
		if(user==null){
			return null;
		}

		//给用户的权限列表赋值
		List<String> authorities=userDao.findRoleByUserId(user.getId());
		int size = authorities==null?0:authorities.size();
		if(size>0){
			List<GrantedAuthority> authorityList=new ArrayList<>(size);
			for(String authority:authorities){
				authorityList.add(new SimpleGrantedAuthority(authority));
			}
			user.setAuthorities(authorityList);
		}

		return user;
	}
}
  • dao接口层

@Mapper
@Repository
public interface UserDao {

    /**
    * [新增]
    * @author 大狼狗
    * @date 2020/03/11
    **/
    int insert(User user);

    /**
    * [刪除]
    * @author 大狼狗
    * @date 2020/03/11
    **/
    int delete(int id);

    /**
    * [更新]
    * @author 大狼狗
    * @date 2020/03/11
    **/
    int update(User user);

    /**
    * [查询] 根据主键 id 查询
    * @author 大狼狗
    * @date 2020/03/11
    **/
    User load(int id);

    /**
    * [查询] 分页查询
    * @author 大狼狗
    * @date 2020/03/11
    **/
    List<User> pageList(@Param("offset") int offset,@Param("pageSize") int pageSize);

    /**
    * [查询] 分页查询 count
    * @author 大狼狗
    * @date 2020/03/11
    **/
    int pageListCount(int offset,int pageSize);

    User findByUsername(String username);

    List<String> findRoleByUserId(Long id);
}

所有需要注意的知识点都以备注的形式写在代码中,请注意查看

demo链接: https://pan.baidu.com/s/1CGMWGtJYZ8uDrjJjlLeLdg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值