Spring Securit学习笔记之整合SSM

Spring Securit学习笔记之整合SSM

1. Spring Security+SSM环境整合

1. 创建maven项目,配置pom.xml

<?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.example</groupId>
  <artifactId>spring_security_ssm</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>spring_security_ssm 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>

    <!-- 规范依赖jar版本 -->
    <spring.version>4.3.10.RELEASE</spring.version>
    <spring.security.version>4.2.3.RELEASE</spring.security.version>
    <jstl.version>1.2</jstl.version>
    <servlet.version>2.5</servlet.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- Spring dependencies -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- Spring Security dependencies -->
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>${spring.security.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>${spring.security.version}</version>
    </dependency>

    <!-- jstl for jsp page dependencies -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>${jstl.version}</version>
    </dependency>

    <!-- servlet-api dependencies -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>


    <!-- jackson 依赖 -->
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.8</version>
    </dependency>

    <!-- 数据库依赖 -->
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.10</version>
    </dependency>

    <!-- spring与mybatis集成依赖 -->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.2</version>
    </dependency>

    <!-- spring与jdbc整合jar -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>

    <!-- spring与测试单元整合jar -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- MyBatis相关包 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.3.0</version>
    </dependency>
    <!-- MySQL相关包 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.26</version>
    </dependency>
    <!-- 日志相关包 -->
    <!--<dependency>-->
      <!--<groupId>log4j</groupId>-->
      <!--<artifactId>log4j</artifactId>-->
      <!--<version>1.2.17</version>-->
    <!--</dependency>-->
  </dependencies>

  <build>
    <finalName>spring_security_ssm</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>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <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>

2. 创建Spring核心配置文件Spring-core.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: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.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.example.service"/>

    <!-- 引入小配置文件 -->
    <context:property-placeholder location="classpath:/jdbc-data.properties"/>
    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!-- 配置创建sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据源 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 指定mapper文件位置 -->
        <property name="mapperLocations" value="classpath:/mapper/*Mapper.xml"></property>
        <!-- 配置别名 -->
        <property name="typeAliasesPackage" value="com.example.entity"></property>
    </bean>
    <!-- 配置创建dao接口实体类 -->
    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <!-- 指定dao接口位置 -->
        <property name="basePackage" value="com.example.dao"></property>
    </bean>

    <!-- 配置事务管理 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据源 -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 开启事务驱动 -->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

3. 创建数据源配置文件jdbc-data.properties

jdbc.url = jdbc:mysql://localhost:3306/security
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.username = root
jdbc.password = root

4. 创建SpringMVC配置文件spring-mvc.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"
       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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 开启控制器注解扫描 -->
    <context:component-scan base-package="com.example.controller"></context:component-scan>


    <!-- 开启springmvc注解扫描驱动 -->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 过滤静态资源,静态资源不做处理 -->
    <!--<mvc:default-servlet-handler></mvc:default-servlet-handler>-->

    <!-- 配置试图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置前缀 -->
        <property name="prefix" value="/jsp/"></property>
        <!-- 配置后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

5. 创建Spring Security配置文件spring-security.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:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:http-basic: 使用 HttpBasic 方式进行登录(认证) -->
        <!--<security:http-basic/>-->

        <!-- security:form-login: 使用 FormLogin 方式进行登录(认证) -->
        <security:form-login/>
    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="username" password="123456" authorities="ROLE_USER,ROLE_ADMIN"/>
                <security:user name="username" password="123456" authorities="ROLE_USER"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

6. 配置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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

  <!-- SpringSecurity 过滤器链 -->
  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- 启动 Spring 配置spring工厂监听器 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- 全局加载配置文件 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      classpath:/spring-core.xml
      classpath:/spring-security.xml
    </param-value>
  </context-param>

  <!-- 启动 SpringMVC 配置核心入口servlet -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 指定servlet去哪加载springmvc的配置文件 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:/spring-mvc.xml</param-value>
    </init-param>
    <!-- 服务器启动加载 Servlet 优先级 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

7. 创建数据库表

表设计

1. 创建sys_user表

id	int(10) NOT NULL
username varchar(50) DEFAULT NULL
realname varchar(50) DEFAULT NULL
password varchar(50) DEFAULT NULL
createDate date DEFAULT NULL
lastLoginTime date DEFAULT NULL
enabled int(5) DEFAULT NULL
accountNonExpired int(5) DEFAULT NULL
accountNonLocked int(5) DEFAULT NULL
credentialsNonExpired int(5) DEFAULT NULL

2. 创建sys_role表

id int(10) NOT NULL
roleName varchar(50) DEFAULT NULL
roleDesc varchar(50) DEFAULT NULL

3. 创建sys_permission表

id int(10) NOT NULL
permName varchar(50) DEFAULT NULL
permTag varchar(50) DEFAULT NULL

4. 创建sys_user_role表

user_id int(10)
role_id int(10)

5. 创建sys_role_permission表

role_id int(10)
perm_id int(10)

8. 创建实体类

1. User.java

package com.example.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class User implements UserDetails {
    private Integer id; //int(10) NOT NULL,
    private String username; //varchar(50) DEFAULT NULL,
    private String realname; //varchar(50) DEFAULT NULL,
    private String password; //varchar(50) DEFAULT NULL,
    private Date createDate; //date DEFAULT NULL,
    private Date lastLoginTime; //date DEFAULT NULL,
    private boolean enabled; //int(5) DEFAULT NULL,
    private boolean accountNonExpired; //int(5) DEFAULT NULL,
    private boolean accountNonLocked; //int(5) DEFAULT NULL,
    private boolean credentialsNonExpired; //int(5) DEFAULT NULL,
    //用户拥有的所有权限
    private List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    public List<GrantedAuthority> getAuthorities() {
        return authorities;
    }
    public void setAuthorities(List<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    @Override
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getRealname() {
        return realname;
    }
    public void setRealname(String realname) {
        this.realname = realname;
    }
    @Override
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Date getCreateDate() {
        return createDate;
    }
    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }
    public Date getLastLoginTime() {
        return lastLoginTime;
    }
    public void setLastLoginTime(Date lastLoginTime) {
        this.lastLoginTime = lastLoginTime;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }
    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }
    @Override
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }
    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }
    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }
}

2. Role.java

package com.example.entity;

public class Role {
    private Integer id; //int(10) NOT NULL,
    private String roleName; //varchar(50) DEFAULT NULL,
    private String roleDesc; //varchar(50) DEFAULT NULL,
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getRoleName() {
        return roleName;
    }
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
    public String getRoleDesc() {
        return roleDesc;
    }
    public void setRoleDesc(String roleDesc) {
        this.roleDesc = roleDesc;
    }
}

3. Permission.java

package com.example.entity;

public class Permission {
    private Integer id; //int(10) NOT NULL,
    private String permName; //varchar(50) DEFAULT NULL,
    private String permTag; //varchar(50) DEFAULT NULL,
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getPermName() {
        return permName;
    }
    public void setPermName(String permName) {
        this.permName = permName;
    }
    public String getPermTag() {
        return permTag;
    }
    public void setPermTag(String permTag) {
        this.permTag = permTag;
    }
}

9. 创建dao接口UserDao.java

package com.example.dao;

import com.example.entity.Permission;
import com.example.entity.User;

import java.util.List;

public interface UserDao {
    /**
     * 查询当前用户对象
     */
    public User findByUsername(String username);
    /**
     * 查询当前用户拥有的权限
     */
    public List<Permission> findPermissionByUsername(String username);
}

10. 创建dao接口的sql映射文件MyMapper.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.example.dao.UserDao">

    <!-- 查询用户 -->
    <select id="findByUsername" parameterType="string" resultType="user">
      select * from sys_user where username = #{value}
    </select>

    <!-- 查询用户的权限 -->
    <select id="findPermissionByUsername" parameterType="string" resultType="permission">
        select permission.*
        from sys_user user
            inner join sys_user_role user_role on user.id = user_role.user_id
            inner join sys_role_permission role_permission on user_role.role_id = role_permission.role_id
            inner join sys_permission permission on role_permission.perm_id = permission.id
        where user.username = #{value};
    </select>
</mapper>

11. 开发测试类

package com.example.test;

import com.example.dao.UserDao;
import com.example.entity.Permission;
import com.example.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/spring-core.xml")
public class UserDaoTest {
    @Autowired
    private UserDao userDao;
    @Test
    public void testFindByUsername(){
        User user = userDao.findByUsername("user");
        System.out.println(user);
    }
    @Test
    public void testFindPermissionByUsername() {
        List<Permission> list = userDao.findPermissionByUsername("user");
        for (Permission perm : list) {
            System.out.println(perm.getPermName() + "-" + perm.getPermTag());
        }
    }
}

2. 自定义 UserDetailService 实现动态数据权限访问

  1. 配置spring-security.xml文件
    	......
    
    	<security:authentication-manager>
        	<security:authentication-provider user-service-ref="myUserDetailSerivce">
    		......
        	</security:authentication-provider>
    	</security:authentication-manager>
    
    	......
    
    	<!-- 将UserDetailService的实现类MyUserDetailService注入spring容器 -->
    	<bean id="myUserDetailSerivce" class="com.example.config.MyUserDetailService"/>
    
    	......
    
    
  2. 开发UserDetailService接口实现类MyUserDetailService.java
    package com.example.config;
    
    import com.example.dao.UserDao;
    import com.example.entity.Permission;
    import com.example.entity.User;
    import org.apache.log4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyUserDetailService implements UserDetailsService {
        private Logger logger = Logger.getLogger(MyUserDetailService.class);
        @Autowired
        private UserDao userMapper;
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //根据用户名查询用户信息
            User user = userMapper.findByUsername(username);
            //根据用户名查询当前用户所有权限
            List<Permission> permList = userMapper.findPermissionByUsername(username);
            //authorities:存放所有用户权限
            List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
            for(Permission perm:permList){
                GrantedAuthority authority = new SimpleGrantedAuthority(perm.getPermTag());
            	authorities.add( authority );
        	}
    	    //把所有权限赋值给 user
            user.setAuthorities(authorities);
            logger.info("当前用户:"+user);
            return user;
        }
    }
    

3. 登录成功与登录失败处理

1. 同步方式处理

配置spring-security.xml文件


......

	<security:form-login login-page="/userLogin"
				 	 authentication-failure-url="/userLogin?error=true"
					 authentication-success-forward-url="/product/index"/>
......

2. 异步方式处理

配置spring-security.xml文件与开发的处理类AuthenticationSuccessHandler与AuthenticationFailureHandler接口的实现类参考以下博文内容

https://blog.csdn.net/qq_43225978/article/details/88685070#5__675

4. PasswordEncoder 密码加密

关键:PasswordEncoder 接口的实现类

配置spring security.xml文件

......

	<security:authentication-manager>
        <security:authentication-provider user-service-ref="myUserDetailSerivce">

            <!--<security:user-service>-->
                <!--<security:user name="username" password="123456" authorities="ROLE_USER,ROLE_ADMIN"/>-->
                <!--<security:user name="username" password="123456" authorities="ROLE_USER"/>-->
            <!--</security:user-service>-->

            <!--使用加密算法对用户输入的密码进入加密,然后和数据库的密码进行配对 -->
            <security:password-encoder ref="passwordEncoder"/>

        </security:authentication-provider>
    </security:authentication-manager>

......

	<!-- 注入加密算法到spring容器 -->
	<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

......

5. RememberMe 记住我

1. 在登录页面添加 remember-me

在登陆页面userLogin.jsp中添加如下内容:

......
<td>记住我:<input type="checkbox" name="remember-me" value="true"></td>
......

完整登陆页面userLogin.jsp:

<%@page pageEncoding="UTF-8" isELIgnored="false"%>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>Hello World!</h2>
<h3>表单登录</h3>
<form action="/login" method="post" id="loginForm">
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" name="password"></td>
        </tr>
        <tr>
            <td>记住我:<input type="checkbox" name="remember-me" value="true"></td>
            <td colspan="2"><button type="submit">登录</button></td>
        </tr>

    </table>
</form>
</body>
</html>

2. 配置spring-security.xml

在spring-security.xml配置文件中添加如下内容:


......

	<!-- 加上 rememberMe 功能 -->
    <!-- token-validity-seconds: 有效秒数 -->
    <security:remember-me token-repository-ref="jdbcTokenRepository" token-validity-seconds="3600"/>

......

	<bean id="jdbcTokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <property name="dataSource" ref="dataSource"/>
        <property name="createTableOnStartup" value="true"/>
    </bean>

......

完整spring-security.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:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/userLogin.jsp" access="permitAll()"/>
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:http-basic: 使用 HttpBasic 方式进行登录(认证) -->
        <!--<security:http-basic/>-->

        <!-- security:form-login: 使用 FormLogin 方式进行登录(认证) -->
        <security:form-login login-page="/userLogin.jsp" login-processing-url="/login"/>

        <!-- 权限不足处理 -->
        <security:access-denied-handler error-page="/error"/>
        <security:csrf disabled="true"/>

        <!-- 加上 rememberMe 功能 -->
        <!-- token-validity-seconds: 有效秒数 -->
        <security:remember-me token-repository-ref="jdbcTokenRepository" token-validity-seconds="3600"/>

    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="myUserDetailSerivce">

            <!--<security:user-service>-->
                <!--<security:user name="username" password="123456" authorities="ROLE_USER,ROLE_ADMIN"/>-->
                <!--<security:user name="username" password="123456" authorities="ROLE_USER"/>-->
            <!--</security:user-service>-->

            <!--使用加密算法对用户输入的密码进入加密,然后和数据库的密码进行配对 -->
            <!--<security:password-encoder ref="passwordEncoder"/>-->

        </security:authentication-provider>
    </security:authentication-manager>

    <!-- 将UserDetailService的实现类MyUserDetailService注入spring容器 -->
    <bean id="myUserDetailSerivce" class="com.example.config.MyUserDetailService"/>

    <!-- 注入加密算法到spring容器 -->
    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

    <bean id="jdbcTokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <property name="dataSource" ref="dataSource"/>
        <property name="createTableOnStartup" value="true"/>
    </bean>
</beans>

6. Spring Security 权限标签使用

1. 引入标签库的依赖坐标

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

2. 在 JSP 页面导入标签库

在productAdd.jsp页面导入以下内容:

<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>

3. 使用 Security 标签

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>欢迎增加</h1>
<a href="/product/index">index</a>

<br/>
===================
<br/>
<security:authorize access="hasAuthority('ROLE_ADD_PRODUCT')" >
    <a href="${pageContext.request.contextPath}/product/add">商品添加</a><br/>
</security:authorize>
<security:authorize access="hasAuthority('ROLE_UPDATE_PRODUCT')">
    <a href="${pageContext.request.contextPath}/product/update">商品修改</a><br/>
</security:authorize>
<security:authorize access="hasAuthority('ROLE_LIST_PRODUCT')">
    <a href="${pageContext.request.contextPath}/product/list">商品查询</a><br/>
</security:authorize>
<security:authorize access="hasAuthority('ROLE_DELETE_PRODUCT')">
    <a href="${pageContext.request.contextPath}/product/delete">商品删除</a><br/>
</security:authorize>
===================

</body>
</html>

7. 如何获取登录后用户名

关键点:SecurityContextHolder 接口,用于操作认证信息。

  1. 在ProductController.java中添加如下内容:
    
    ......
    
    /**
     * 商品添加
     */
    @RequestMapping("/add")
    public String add(Model model){
        //获取登录后用户: UserDetail 对象
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(principal!=null){
            if(principal instanceof UserDetails){
                UserDetails userDetails = (UserDetails)principal;
                String username = userDetails.getUsername();
                model.addAttribute("username",username);
                System.out.println(username);
            }
        }
        return "product/productAdd";
    }
    
    ......
    
    
  2. 在productAdd.jsp页面添加如下内容:
    ......
    用户名:${requestScope.username}
    ......
    
posted @ 2019-03-22 17:01  IT-小浣熊  阅读(74)  评论(0)    收藏  举报