转载

springSecurity02(mybatis+springmvc+spring) 01

1.建立一个模块继承上一个模块然后添加依赖

<dependencies>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.8</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
    </dependencies>
  
    <!--解决打包时找不到xml文件-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

2.建立数据源文件application.properties

#数据库连接相关
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/security-demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username = root
jdbc.password = 123456

3.修改applicationContext.xml,配置数据源,和mybatis整合,以及事务管理

<?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:tx="http://www.alibaba.com/schema/stat"
       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 http://www.alibaba.com/schema/stat http://www.alibaba.com/schema/stat.xsd">

    <!-- 自动扫描 -->
    <context:component-scan base-package="com.ty">
        <!-- 扫描时跳过 @TestController 注解的JAVA类(控制器) -->
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller" />
        <context:exclude-filter type="annotation"
                                expression="org.springframework.web.bind.annotation.ControllerAdvice" />
    </context:component-scan>

    <!--扫描配置文件(这里指向的是之前配置的那个config.properties) -->
    <context:property-placeholder location="classpath:application.properties" />

    <!--配置数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}" />  <!--数据库连接驱动 -->
        <property name="url" value="${jdbc.url}" />     <!--数据库地址 -->
        <property name="username" value="${jdbc.username}" />   <!--用户名 -->
        <property name="password" value="${jdbc.password}" />   <!--密码 -->
        <property name="maxActive" value="40" />      <!--最大连接数 -->
        <property name="minIdle" value="1" />       <!--最小连接数 -->
        <property name="initialSize" value="10" />      <!--初始化连接池内的数据库连接 -->
        <property name="maxWait" value="20" />  <!--最大空闲时间 -->
    </bean>

    <!--mybatis与spring整合 -->
    <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--配置别名扫描包-->
        <property name="typeAliasesPackage" value="com.ty.pojo"></property>
        <property name="mapperLocations" value="classpath:com.ty.mapper/*.xml"></property>
    </bean>

    <!--扫描接口-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.ty.mapper"></property>
    </bean>

   <!--事务配置-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--开启事务-->
    <tx:annotation-drive
![图片上传中...]
n/>

</beans>

目录结构,我这里测试mybatis时放在同一包出问题,所以选择了分别扫描xml和mapper接口

springSecurity02(mybatis+springmvc+spring) 01

数据库,总共建立了5张表,用户表,角色表,用户角色对应表,权限表,权限角色对应表,关系也很简单,一个用户有多个角色,一个角色也可以有多个用户拥有,一个角色有多种权限,一个权限也可以由多个角色掌握,这个看自己怎么设计,其中用户表最重要,这里面包含了用户的基本信息

/*
Navicat MySQL Data Transfer

Source Server         : security
Source Server Version : 50719
Source Host           : localhost:3306
Source Database       : security-demo

Target Server Type    : MYSQL
Target Server Version : 50719
File Encoding         : 65001

Date: 2019-08-02 10:25:48
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for sys_authorization
-- ----------------------------
DROP TABLE IF EXISTS `sys_authorization`;
CREATE TABLE `sys_authorization` (
  `id` int(11) NOT NULL,
  `authorizationName` varchar(50) DEFAULT NULL,
  `authorizationMark` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_authorization
-- ----------------------------
INSERT INTO `sys_authorization` VALUES ('1', '产品查询', 'ROLE_LIST_PRODUCT');
INSERT INTO `sys_authorization` VALUES ('2', '产品添加', 'ROLE_ADD_PRODUCT');
INSERT INTO `sys_authorization` VALUES ('3', '产品修改', 'ROLE_UPDATE_PRODUCT');
INSERT INTO `sys_authorization` VALUES ('4', '产品删除', 'ROLE_DELETE_PRODUCT');

-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
  `id` int(11) NOT NULL,
  `roleName` varchar(50) DEFAULT NULL,
  `roleDescription` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', '普通用户', '普通用户');
INSERT INTO `sys_role` VALUES ('2', '管理员', '管理员');

-- ----------------------------
-- Table structure for sys_role_authorization
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_authorization`;
CREATE TABLE `sys_role_authorization` (
  `roleId` int(11) NOT NULL,
  `authorizationId` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role_authorization
-- ----------------------------
INSERT INTO `sys_role_authorization` VALUES ('1', '1');
INSERT INTO `sys_role_authorization` VALUES ('1', '2');
INSERT INTO `sys_role_authorization` VALUES ('2', '1');
INSERT INTO `sys_role_authorization` VALUES ('2', '2');
INSERT INTO `sys_role_authorization` VALUES ('2', '3');
INSERT INTO `sys_role_authorization` VALUES ('2', '4');

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `realname` varchar(50) DEFAULT NULL,
  `createDate` date DEFAULT NULL,
  `lastLoginTime` date DEFAULT NULL,
  `enabled` int(11) DEFAULT NULL,
  `accountNonExpired` int(11) DEFAULT NULL,
  `accountNonLocked` int(11) DEFAULT NULL,
  `credentialsNonExpired` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', 'jojo', '$2a$10$VCvgzml/DNzBTkjsPlImDuZp38sNZB7cEmsNgFIWBm/Vtpn0Q3Bj.', '张三', '2019-06-26', '2019-08-01', '1', '1', '1', '1');
INSERT INTO `sys_user` VALUES ('2', 'jack', '$2a$10$W1T2Z5dUMIgBfxvFdBOWuusq8Nwke/cQydxDFemsbTh0PjGeZCiMC', '李四', '2019-07-30', '2019-08-01', '1', '1', '1', '1');

-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `userId` int(11) NOT NULL,
  `roleId` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1', '1');
INSERT INTO `sys_user_role` VALUES ('2', '2');

基本配置完成

在mapper文件夹下建立UserMapper接口

package com.ty.mapper;

import com.ty.pojo.Authorization;
import com.ty.pojo.User;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

/**
 * @Author:TY
 * @Descroption:
 * @Date: Created in 11:34 2019/8/1
 * @Modificd By:
 */
public interface UserMapper {

    @Select("select * from sys_user")
    List<User> findAll();
    /**
     * 查询当前用户对象
     */

    public User findByUserName(String username);


    /**
     * 查询当前用户的权限
     */
    List<Authorization> findAuthorizationByUserName(String username);

    /**
     * 修改密码
     */

    @Update("update sys_user set password=#{password} where username=#{username}")
    public void updatePassword(User user);


}

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.ty.mapper.UserMapper">


    <select id="findByUserName" resultType="User" parameterType="String">
         SELECT * FROM sys_user where username = #{username}
    </select>


    <select id="findAuthorizationByUserName" parameterType="String" resultType="Authorization">
          SELECT a.* from sys_user u ,sys_user_role ur,sys_role_authorization ra,sys_authorization a
          WHERE u.id=ur.userId  and ur.roleId= ra.roleId and ra.authorizationId=a.id
          AND u.username=#{username}
    </select>
</mapper>

想要测试就这样

springSecurity02(mybatis+springmvc+spring) 01

在MainController里面添加一个验证码接口(生成验证码网上都有,这里就不列出了)

@RequestMapping("/imageCode")
    public void imageCode(HttpServletRequest request, HttpServletResponse response) throws Exception {

//        ImageCodeProcessor.send(new ServletWebRequest(request,response),new ImageCodeGenerator().generate(new ServletWebRequest(request)));
        ImageCode generate = new ImageCodeGenerator().generate(new ServletWebRequest(request));
        HttpSession session = request.getSession();
        System.out.println("生成的验证码为:"+generate.getCode());
        session.setAttribute("key",generate.getCode());
        response.setContentType("image/jpeg");
        // 将图像输出到Servlet输出流中。
        ServletOutputStream sos = response.getOutputStream();
        ImageIO.write(generate.getImage(), "jpeg", sos);
        sos.close();
    }

pojo包中的User对象,里面添加了一个权限的字段,是user表中没有的,并且User对象实现了UserDetails接口,实现了其中的方法,方便后面security使用

package com.ty.pojo;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.Date;
import java.util.List;

public class User implements UserDetails{

  private Integer id;
  private String username;
  private String password;
  private String realname;
  private java.util.Date createDate;
  private java.util.Date lastLoginTime;
  private boolean enabled;
  private boolean accountNonExpired;
  private boolean accountNonLocked;
  private boolean credentialsNonExpired;

  //用户拥有的所有权限
  List<GrantedAuthority>  authorities=new ArrayList<>();

  @Override
  public String toString() {
    return "User{" +
            "username='" + username + '/'' +
            ", realname='" + realname + '/'' +
            ", authorities=" + authorities +
            '}';
  }

  @Override
  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  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;
  }

  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;
  }

  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;
  }

  public boolean isEnabled() {
    return enabled;
  }

  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }

  public boolean isAccountNonExpired() {
    return accountNonExpired;
  }

  public void setAccountNonExpired(boolean accountNonExpired) {
    this.accountNonExpired = accountNonExpired;
  }

  public boolean isAccountNonLocked() {
    return accountNonLocked;
  }

  public void setAccountNonLocked(boolean accountNonLocked) {
    this.accountNonLocked = accountNonLocked;
  }

  public boolean isCredentialsNonExpired() {
    return credentialsNonExpired;
  }

  public void setCredentialsNonExpired(boolean credentialsNonExpired) {
    this.credentialsNonExpired = credentialsNonExpired;
  }
}

其它表就直接用idea自带的工具:数据库生成pojo类执行就行了

springSecurity02(mybatis+springmvc+spring) 01

连接数据库点击

springSecurity02(mybatis+springmvc+spring) 01

springSecurity.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.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-4.2.xsd">
    <!--  <security:http>:对web.xml中spring过滤器链的配置:web.xml里面的过滤器接受到请求,就会根据这个配置去过滤
    1)需要拦截什么资源
    2)什么资源什么角色权限
    3)定义认证方式:HttpBasic,FormLogin
    4)定义登陆页面,定义登陆请求地址,定义错误处理方式
    用于授权
    -->
    <security:http>
        <security:intercept-url pattern="/product/index" access="permitAll()"></security:intercept-url>
        <security:intercept-url pattern="/product/list" access="hasAuthority('ROLE_LIST_PRODUCT')"></security:intercept-url>
        <security:intercept-url pattern="/product/add" access="hasAuthority('ROLE_ADD_PRODUCT')"></security:intercept-url>
        <security:intercept-url pattern="/product/update" access="hasAuthority('ROLE_UPDATE_PRODUCT')"></security:intercept-url>
        <security:intercept-url pattern="/product/delete" access="hasAuthority('ROLE_DELETE_PRODUCT')"></security:intercept-url>
        <security:intercept-url pattern="/js/**" access="permitAll()"></security:intercept-url>

        <security:intercept-url pattern="/imageCode" access="permitAll()"></security:intercept-url>

        <security:intercept-url pattern="/userLogin" access="permitAll()"></security:intercept-url>
        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"></security:intercept-url>



        <!--自定义SpringSecurity过滤器-->
        <security:custom-filter ref="imageCodeAuthenticationFilter" before="FORM_LOGIN_FILTER"/>

        <security:form-login login-page="/userLogin" login-processing-url="/login"
                             authentication-success-handler-ref="mySuccessAthenticationHandler"
                            authentication-failure-handler-ref="myAuthenticationFailureHandler"/>


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

        <!--加上rememberme的功能-->
        <!--token-validity-seconds:cookie过期时间-->
        <security:remember-me token-repository-ref="jdbcTokenRepository" token-validity-seconds="3600"></security:remember-me>
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider user-service-ref="myUserDetailService">
            <!--使用加密的算法,然后再和数据库密码配对-->
            <security:password-encoder ref="passwordEncoder"></security:password-encoder>
        </security:authentication-provider>
    </security:authentication-manager>


    <bean id="imageCodeAuthenticationFilter" class="com.ty.security.ImageCodeAuthenticationFilter">
        <property name="authenticationFailureHandler" ref="myAuthenticationFailureHandler"></property>
    </bean>

    <bean id="myUserDetailService" class="com.ty.security.MyUserDetailService"></bean>
    <bean id="mySuccessAthenticationHandler" class="com.ty.security.MySuccessAthenticationHandler"></bean>

    <!--失败处理器-->
    <bean id="myAuthenticationFailureHandler" class="com.ty.security.MyAuthenticationFailureHandler"></bean>

    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>


    <!--rememberme功能的bean-->
    <bean id="jdbcTokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <property name="dataSource" ref="dataSource"></property>
        <!--启动的时候生成表persistent_logins,但是有的话一定要把数据库的表删掉或者把这个注释掉-->
        <!--<property name="createTableOnStartup" value="true"></property>-->
    </bean>
</beans>

MyUserDetailService :这里就动态在数据库里面动态查询了用户的权限,然后因为之前我们的User类实现了UserDetails接口,所以当返回我们自己从数据库查询的用户然后返回的时候,springSecurity会自己拿着用户输入的信息和我们数据库中的做一个比对,对比上了则认证成功

package com.ty.security;

import com.ty.mapper.UserMapper;
import com.ty.pojo.Authorization;
import com.ty.pojo.User;
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;

/**
 * @Author:TY
 * @Descroption:
 * @Date: Created in 17:09 2019/8/1
 * @Modificd By:
 */
public class MyUserDetailService implements UserDetailsService{
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user=null;
        System.out.println(username);
        if(username!=null&&!username.equals(""))
        {
              user = userMapper.findByUserName(username);
            if (user!=null)
            {
                //获取用户权限
                List<Authorization>  permList = userMapper.findAuthorizationByUserName(username);
                List<GrantedAuthority> authorizations=new ArrayList<>();
                for (Authorization perm:permList)
                {
                     GrantedAuthority authority=new SimpleGrantedAuthority(perm.getAuthorizationMark());
                     authorizations.add(authority);
                }
                user.setAuthorities(authorizations);
            }
            return user;
        }

        return user;
    }

}

然后我们自定义成功后的处理器MySuccessAthenticationHandler

package com.ty.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author:TY
 * @Descroption:
 * @Date: Created in 19:43 2019/8/1
 * @Modificd By:
 */
public class MySuccessAthenticationHandler implements AuthenticationSuccessHandler {
    private static final ObjectMapper objectMapper=new ObjectMapper();
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        Map map=new HashMap();
        map.put("success",true);
        String result = objectMapper.writeValueAsString(map);
        httpServletResponse.setContentType("text/json;charset=utf-8");
        httpServletResponse.getWriter().write(result);
    }
}

失败处理器:

package com.ty.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author:TY
 * @Descroption:
 * @Date: Created in 21:23 2019/7/31
 * @Modificd By:
 */
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler{
    private    ObjectMapper objectMapper=new ObjectMapper();
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        Map map=new HashMap();
        map.put("success",false);
        map.put("errorMsg",e.getMessage());
        String result = objectMapper.writeValueAsString(map);
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(result);
    }
}

登录的时候是先验证验证码,验证码通过在验证用户名和密码

验证码的拦截器

package com.ty.security;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @Author:TY
 * @Descroption:,他能够确保在一次请求只通过一次filter,而不需要重复执行
 *
 * @Date: Created in 21:22 2019/8/1
 * @Modificd By:
 */
public class ImageCodeAuthenticationFilter extends OncePerRequestFilter {

    private AuthenticationFailureHandler authenticationFailureHandler;


    public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
        this.authenticationFailureHandler = authenticationFailureHandler;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        //判断当前请求,是否为登录请求,
        if (request.getRequestURI().contains("/login"))
        {
           try {
               //校验验证码
               //表单填的验证码
               String imageCode = request.getParameter("imageCode");
               System.out.println("表单填的验证码为:"+imageCode);
               //系统生成的验证码
               HttpSession session = request.getSession();
               String  sesstionCode = (String) session.getAttribute("key");
               System.out.println("session里的验证码为:"+sesstionCode);
               if(imageCode==null||imageCode.equals(""))
               {
                   throw new ImageCodeException("验证码不能为空");
               }
               if(!imageCode.equals(sesstionCode))
               {
                   throw new ImageCodeException("验证码错误");
               }
           }catch (AuthenticationException e){
             //交给自定义的
               authenticationFailureHandler.onAuthenticationFailure(request,response,e);
               return;
           }
        }
        filterChain.doFilter(request,response);
    }
}

验证码异常类

package com.ty.security;


import org.springframework.security.core.AuthenticationException;

/**
 * @Author:TY
 * @Descroption:
 * @Date: Created in 21:47 2019/8/1
 * @Modificd By:
 */
public class ImageCodeException extends AuthenticationException {

    public ImageCodeException(String msg, Throwable t) {
        super(msg, t);
    }

    public ImageCodeException(String msg) {
        super(msg);
    }
}

注意:我们是把验证码过滤器加在UserNamePasswordAuthenticationFilter前面的,当我们的验证码抛出异常,验证码没通过时会抛一个ImageCodeException,这个类继承了AuthenticationException ,所以当抛出异常之后会到我们自定义的MyAuthenticationFailureHandler,这样就可以向前端返回异常的数据

login.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: TY
  Date: 2019/7/31
  Time: 19:14
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录页面</title>
</head>
<body>
<c:if test="${not empty param.error}">
    <font color="red">用户名或密码错误</font>
</c:if>
<form id="loginForm">
    用户名:<input type="text" name="username"><br>
    密 码:<input type="password" name="password"><br>
    验证码:<input type="text" name="imageCode"><img id="imgcheck" src="/imageCode"><br>
    <input type="checkbox" name="remember-me" value="true">记住我
    <input type="button" id="LoginButton" value="登录">
</form>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
<script type="text/javascript">
    $(function () {
        $("#LoginButton").click(function () {
            $.post("/login", $("#loginForm").serialize(), function (data) {
                if (data.success) {
                    window.location.href = "${pageContext.request.contextPath}/product/index";
                } else {
                    alert("登录失败:" + data.errorMsg);
                }
            }, "json");
        })
    })
    window.onload = function () {
        var date = new Date();
        $("#imgcheck").click(function () {
            $(this).attr('src', "/imageCode?temp=" + date);
        });
    }
</script>

</body>
</html>

如果要根据权限显示前端内容,就在pom.xml引入

<dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-taglibs</artifactId>
      <version>4.2.3.RELEASE</version>
    </dependency>

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: TY
  Date: 2019/7/31
  Time: 16:49
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
<c:if test="${username != null}">
    <span>欢迎${username}登陆</span>
</c:if>
以下是网站的功能
<security:authorize access="hasAuthority('ROLE_ADD_PRODUCT')">
    <a href="/product/add">商品添加</a>
</security:authorize>
<security:authorize access="hasAuthority('ROLE_UPDATE_PRODUCT')">
    <a href="/product/update">商品修改</a>
</security:authorize>
<security:authorize access="hasAuthority('ROLE_LIST_PRODUCT')">
    <a href="/product/list">商品查询</a>
</security:authorize>

<security:authorize access="hasAuthority('ROLE_DELETE_PRODUCT')">
    <a href="/product/delete">商品删除</a>
</security:authorize>
</body>
</html>

**最后如果想要获取认证通过后的用户的信息,任何地方都能获取

可以使用SecurityContextHolder.getContext().getAuthentication().getPrincipal()

/**
     * 首页  SecurityContextHolder.getContext().getAuthentication().getPrincipal()可以在任何地方获取当前用户的信息
     */
    @RequestMapping("index")
    public String index(Model model)
    {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(principal!=null)
        {
            if(principal instanceof UserDetails)
            {
               UserDetails userDetails= (UserDetails)principal;
               model.addAttribute("username",userDetails.getUsername());
            }
        }
        return "index";
    }

**

原文  https://segmentfault.com/a/1190000019951843
正文到此结束
Loading...