• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

微服务多模块Springboot+Security+Redis+JWT 仅需一招

武飞扬头像
Lino_white
帮助1

小编在开发阶段发现,在现在众多文章中的教程里,虽然有许许多多的Springboot Security Redis JWT,但是那些教程基本的运行环境都在单个项目单个模块中进行开发和测试的,这使得小编在实际的开发过程中,不能Ctrl C and Ctrl V直接完全解决这个登录认证的事情。故有这篇文章。

 

目录

 

1.项目结构

2.Common模块

pom.xml

2.1 RedisConfig

2.2 RedisUtil

2.3 ResponseUtil

2.4  TokenUtil

3.model模块

3.1 User

4.service模块

pom.xml

4.1 UserMapper

4.2 重点说明

4.3 MyUserDetailService

5.spring_security模块

5.1 DiyUserDetails(UserDetails)

5.2 WebSecurityConfig(WebSecurityConfigurerAdapter)

5.3 TokenAuthenticationFilter(BasicAuthenticationFilter)

5.4 TokenLoginFilter(UsernamePasswordAuthenticationFilter)

5.5 TokenOncePerRequestFilter(OncePerRequestFilter)

5.6 LoginAuthenticationEntryPoint(AuthenticationEntryPoint)

5.7 LoginInFailHandler(AuthenticationFailureHandler)

5.8 LoginInSuccessHandler(AuthenticationSuccessHandler)

5.9 LogOutSuccessHandler(LogoutSuccessHandler)

5.10 NothingAccessDeniedHandler(AccessDeniedHandler)

6.测试


1.项目结构

学新通

涉及的模块有common(Redis配置文件、Redis工具、Token工具、返回信息的工具;即如下文件RedisConfig、RedisUtil、TokenUtil、ResponseUtil)、model(user的实体类)、service(主要利用MySQL查询用户数据)、spring_security(多个配置文件,配置security的)。

下面小编将全部一个一个地介绍并且源码展示出来。

2.Common模块

pom.xml

  1.  
    <!--security安全框架-->
  2.  
    <dependency>
  3.  
    <groupId>org.springframework.boot</groupId>
  4.  
    <artifactId>spring-boot-starter-security</artifactId>
  5.  
    </dependency>
  6.  
     
  7.  
    <!--springboot_redis缓存框架 -->
  8.  
    <dependency>
  9.  
    <groupId>org.springframework.boot</groupId>
  10.  
    <artifactId>spring-boot-starter-data-redis</artifactId>
  11.  
    </dependency>
  12.  
     
  13.  
    <dependency>
  14.  
    <groupId>io.jsonwebtoken</groupId>
  15.  
    <artifactId>jjwt</artifactId>
  16.  
    </dependency>
学新通

2.1 RedisConfig

  1.  
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
  2.  
    import com.fasterxml.jackson.annotation.PropertyAccessor;
  3.  
    import com.fasterxml.jackson.databind.ObjectMapper;
  4.  
    import org.springframework.cache.annotation.CachingConfigurerSupport;
  5.  
    import org.springframework.cache.annotation.EnableCaching;
  6.  
    import org.springframework.context.annotation.Bean;
  7.  
    import org.springframework.context.annotation.Configuration;
  8.  
    import org.springframework.data.redis.connection.RedisConnectionFactory;
  9.  
    import org.springframework.data.redis.core.RedisTemplate;
  10.  
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  11.  
    import org.springframework.data.redis.serializer.StringRedisSerializer;
  12.  
     
  13.  
    import javax.annotation.Resource;
  14.  
    /*
  15.  
    * Redis配置
  16.  
    * 解决redis在业务逻辑处理层上不出错,缓存序列化问题
  17.  
    * */
  18.  
    @Configuration
  19.  
    @EnableCaching
  20.  
    public class RedisConfig extends CachingConfigurerSupport {
  21.  
    @Resource
  22.  
    RedisConnectionFactory redisConnectionFactory;
  23.  
    @Bean
  24.  
    public RedisTemplate<String,Object> redisTemplate(){
  25.  
    RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
  26.  
    redisTemplate.setConnectionFactory(redisConnectionFactory);
  27.  
    //Json序列化配置
  28.  
    //1、String的序列化
  29.  
    StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
  30.  
    // key采用String的序列化方式
  31.  
    redisTemplate.setKeySerializer(stringRedisSerializer);
  32.  
    // hash的key也采用String的序列化方式
  33.  
    redisTemplate.setHashKeySerializer(stringRedisSerializer);
  34.  
     
  35.  
    //2、json解析任意的对象(Object),变成json序列化
  36.  
    Jackson2JsonRedisSerializer<Object> serializer=new Jackson2JsonRedisSerializer<Object>(Object.class);
  37.  
    ObjectMapper mapper=new ObjectMapper(); //用ObjectMapper进行转义
  38.  
    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  39.  
    //该方法是指定序列化输入的类型,就是将数据库里的数据按照一定类型存储到redis缓存中。
  40.  
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  41.  
    serializer.setObjectMapper(mapper);
  42.  
     
  43.  
    // value序列化方式采用jackson
  44.  
    redisTemplate.setValueSerializer(serializer);
  45.  
    // hash的value序列化方式采用jackson
  46.  
    redisTemplate.setHashValueSerializer(serializer);
  47.  
     
  48.  
    return redisTemplate;
  49.  
    }
  50.  
    }
学新通

2.2 RedisUtil

  1.  
    import org.springframework.beans.factory.annotation.Autowired;
  2.  
    import org.springframework.data.redis.core.StringRedisTemplate;
  3.  
    import org.springframework.stereotype.Component;
  4.  
     
  5.  
    import javax.annotation.PostConstruct;
  6.  
    import java.time.LocalDateTime;
  7.  
    import java.time.format.DateTimeFormatter;
  8.  
    import java.time.temporal.ChronoUnit;
  9.  
    import java.util.concurrent.TimeUnit;
  10.  
     
  11.  
    @Component
  12.  
    public class RedisUtil {
  13.  
    @Autowired
  14.  
    private StringRedisTemplate stringRedisTemplate;
  15.  
    public static StringRedisTemplate stringRedisTemplateStatic;
  16.  
    @PostConstruct //在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。
  17.  
    public void initStringRedisTemplate(){
  18.  
    stringRedisTemplateStatic=this.stringRedisTemplate;
  19.  
    }
  20.  
     
  21.  
    private static final DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  22.  
     
  23.  
    /*
  24.  
    * 保存token信息到redis,也可直接在创建token中使用该方法
  25.  
    * */
  26.  
    public static void redis_SaveTokenInfo(String token,String username){
  27.  
    //以username做key
  28.  
    LocalDateTime localDateTime=LocalDateTime.now();
  29.  
    stringRedisTemplateStatic.opsForHash().put(username,"token",token);
  30.  
    stringRedisTemplateStatic.opsForHash().put(username,"refreshTime", //有效时间
  31.  
    df.format(localDateTime.plus(7*24*60*60*1000, ChronoUnit.MILLIS)));
  32.  
    stringRedisTemplateStatic.opsForHash().put(username,"expiration", //过期时间 5分钟 300秒
  33.  
    df.format(localDateTime.plus(300*1000, ChronoUnit.MILLIS)));
  34.  
    stringRedisTemplateStatic.expire(username,7*24*60*60*1000, TimeUnit.SECONDS);
  35.  
    }
  36.  
     
  37.  
    /*
  38.  
    * 检查redis是否存在token
  39.  
    * */
  40.  
    public static boolean hasToken(String username){
  41.  
    return stringRedisTemplateStatic.opsForHash().getOperations().hasKey(username);
  42.  
    }
  43.  
    }
学新通

2.3 ResponseUtil

  1.  
    import com.fasterxml.jackson.databind.ObjectMapper;
  2.  
    import lombok.Data;
  3.  
    import org.apache.ibatis.annotations.Result;
  4.  
    import org.springframework.http.HttpStatus;
  5.  
    import org.springframework.http.MediaType;
  6.  
     
  7.  
    import javax.servlet.http.HttpServletResponse;
  8.  
    import java.io.IOException;
  9.  
    import java.io.PrintWriter;
  10.  
    import java.util.HashMap;
  11.  
    import java.util.Map;
  12.  
    @Data
  13.  
    public class ResponseUtil {
  14.  
    public static int OK = 200;
  15.  
    public static int ERROR = 404;
  16.  
    public static String SUCCESS="操作成功!";
  17.  
    public static String NO_SUCCESS="操作失败,请稍候重试。";
  18.  
    //返回码(200)
  19.  
    private int code;
  20.  
    //返回消息
  21.  
    private String message;
  22.  
     
  23.  
    @ApiModelProperty(value = "返回数据(单条或多条)")
  24.  
    private Map<Object, Object> data = new HashMap<Object, Object>();
  25.  
     
  26.  
     
  27.  
    public ResponseUtil(int code, String message) {
  28.  
    this.code=code;
  29.  
    this.message=message;
  30.  
    }
  31.  
    public ResponseUtil(int code, String message, Map<Object, Object> data) {
  32.  
    this.code=code;
  33.  
    this.message=message;
  34.  
    this.data=data;
  35.  
    }
  36.  
    //对response写入Object数据
  37.  
    public static void reponseOutDiy(HttpServletResponse response,int statusCode , Object result) {
  38.  
    ObjectMapper mapper = new ObjectMapper();
  39.  
    PrintWriter writer = null;
  40.  
    response.setStatus(statusCode);
  41.  
    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
  42.  
    try {
  43.  
    writer = response.getWriter();
  44.  
    mapper.writeValue(writer, result);
  45.  
    writer.flush();
  46.  
    } catch (IOException e) {
  47.  
    e.printStackTrace();
  48.  
    } finally {
  49.  
    if (writer != null) {
  50.  
    writer.flush();
  51.  
    writer.close();
  52.  
    }
  53.  
    }
  54.  
    }
  55.  
     
  56.  
    }
学新通

2.4  TokenUtil

  1.  
    import com.Lino_white.model.User; //model模块的user
  2.  
    import io.jsonwebtoken.Claims;
  3.  
    import io.jsonwebtoken.Jwts;
  4.  
    import io.jsonwebtoken.SignatureAlgorithm;
  5.  
    import org.springframework.util.StringUtils;
  6.  
     
  7.  
    import javax.servlet.http.HttpServletRequest;
  8.  
    import java.text.ParseException;
  9.  
    import java.text.SimpleDateFormat;
  10.  
    import java.util.Date;
  11.  
    import java.util.Locale;
  12.  
     
  13.  
    public class TokenUtil {
  14.  
    public static final String APP_SECRET ="Lino_white"; //随便取,你的Token密钥
  15.  
    public static final String TOKEN_HEAD="Authorization";
  16.  
     
  17.  
    public static final String TOKEN_PREFIX = "Bearer ";
  18.  
    public static String createToken(User user){
  19.  
    String token = Jwts.builder()
  20.  
    .setId(String.valueOf(user.getId()))
  21.  
    .setSubject(user.getUsername())
  22.  
    .setIssuedAt(new Date()) //签发时间
  23.  
    .setIssuer("Lino_white") //签发者
  24.  
    .setExpiration(new Date(System.currentTimeMillis() 300* 1000)) //过期时间 5分钟
  25.  
    .signWith(SignatureAlgorithm.HS256, APP_SECRET) //签名算法跟密钥
  26.  
    .claim("identity", user.getIdentity()) //可添加额外的属性
  27.  
    .compact();
  28.  
    return token;
  29.  
    }
  30.  
     
  31.  
    //重新生成新的Token,异常时间由传入的参数决定
  32.  
    public static String createToken(User user,Date expirationTime){
  33.  
    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  34.  
    try {
  35.  
    expirationTime= (Date) f.parse(f.format(expirationTime));
  36.  
    } catch (ParseException e) {
  37.  
    throw new RuntimeException(e);
  38.  
    }
  39.  
     
  40.  
    String token = Jwts.builder()
  41.  
    .setId(String.valueOf(user.getId()))
  42.  
    .setSubject(user.getUsername())
  43.  
    .setIssuedAt(new Date()) //签发时间
  44.  
    .setIssuer("Lino_white") //签发者
  45.  
    .setExpiration(expirationTime) //过期时间
  46.  
    .signWith(SignatureAlgorithm.HS256, APP_SECRET) //签名算法跟密钥
  47.  
    .claim("identity", user.getIdentity()) //可添加额外的属性
  48.  
    .compact();
  49.  
    return token;
  50.  
    }
  51.  
     
  52.  
    //获得用户名
  53.  
    public String getUsernameFromToken(String token){
  54.  
    return Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token).getBody().getSubject();
  55.  
    }
  56.  
    /**
  57.  
    * 判断token是否存在与有效(1)
  58.  
    */
  59.  
    public boolean checkToken(String token){
  60.  
    if (StringUtils.isEmpty(token)) return false;
  61.  
    try {
  62.  
    Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token);
  63.  
    }catch (Exception e){
  64.  
    e.printStackTrace();
  65.  
    return false;
  66.  
    }
  67.  
    return true;
  68.  
    }
  69.  
    /**
  70.  
    * 判断token是否存在与有效(2)
  71.  
    */
  72.  
    public boolean checkToken(HttpServletRequest request){
  73.  
    try {
  74.  
    String token = request.getHeader("token");
  75.  
    return checkToken(token);
  76.  
    }catch (Exception e){
  77.  
    e.printStackTrace();
  78.  
    return false;
  79.  
    }
  80.  
    }
  81.  
    //获得全部属性
  82.  
    public Claims parseJwt(String token){
  83.  
    Claims claims = Jwts.parser()
  84.  
    .setSigningKey(APP_SECRET) // 设置标识名
  85.  
    .parseClaimsJws(token) //解析token
  86.  
    .getBody();
  87.  
    return claims;
  88.  
    }
  89.  
    //获得指定属性
  90.  
    public String getTokenClaim(String token,String key){
  91.  
    Claims body = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token).getBody();
  92.  
    return String.valueOf(body.get(key));
  93.  
    }
  94.  
    }
学新通

3.model模块

3.1 User

  1.  
    import com.baomidou.mybatisplus.annotation.IdType;
  2.  
    import com.baomidou.mybatisplus.annotation.TableId;
  3.  
    import com.baomidou.mybatisplus.annotation.TableName;
  4.  
    import lombok.Data;
  5.  
    import java.io.Serializable;
  6.  
     
  7.  
    @Data
  8.  
    //实体:用户
  9.  
    @TableName("user")
  10.  
    public class User implements Serializable {
  11.  
    //用户id
  12.  
    @TableId(type = IdType.AUTO)
  13.  
    private Long id;
  14.  
    //用户名
  15.  
    private String username;
  16.  
    //密码
  17.  
    private String password;
  18.  
    //身份
  19.  
    private String identity;
  20.  
    }
学新通

4.service模块

在这个模块下启动类需要开启SpringBoot:@SpringBootApplication

pom.xml

  1.  
    <dependency>
  2.  
    <groupId>mysql</groupId>
  3.  
    <artifactId>mysql-connector-java</artifactId>
  4.  
    </dependency>
  5.  
     
  6.  
    <dependency>
  7.  
    <groupId>com.baomidou</groupId>
  8.  
    <artifactId>mybatis-plus-boot-starter</artifactId>
  9.  
    </dependency>
  10.  
     
  11.  
    <dependency>
  12.  
    <groupId>com.alibaba</groupId>
  13.  
    <artifactId>fastjson</artifactId>
  14.  
    </dependency>
  15.  
     
  16.  
    <dependency>
  17.  
    <groupId>org.springframework.boot</groupId>
  18.  
    <artifactId>spring-boot-starter-web</artifactId>
  19.  
    </dependency>
  20.  
     
  21.  
    <dependency>
  22.  
    <groupId>org.springframework</groupId>
  23.  
    <artifactId>spring-web</artifactId>
  24.  
    <version>5.3.22</version>
  25.  
    <scope>compile</scope>
  26.  
    </dependency>
  27.  
     
  28.  
    <dependency>
  29.  
    <groupId>com.Lino_white</groupId>
  30.  
    <artifactId>model</artifactId>
  31.  
    <version>1.0-SNAPSHOT</version>
  32.  
    <scope>compile</scope>
  33.  
    </dependency>
  34.  
    <dependency>
  35.  
    <groupId>com.Lino_white</groupId>
  36.  
    <artifactId>common</artifactId>
  37.  
    <version>1.0-SNAPSHOT</version>
  38.  
    <scope>compile</scope>
  39.  
    </dependency>
  40.  
    <dependency>
  41.  
    <groupId>com.Lino_white</groupId>
  42.  
    <artifactId>spring_security</artifactId>
  43.  
    <version>1.0-SNAPSHOT</version>
  44.  
    </dependency>
学新通

4.1 UserMapper

  1.  
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  2.  
    import com.Lino_white.model.User;
  3.  
    import org.apache.ibatis.annotations.Select;
  4.  
     
  5.  
    public interface UserMapper extends BaseMapper<User> {
  6.  
    @Select("select * from user where username=#{username}")
  7.  
    User findUserByName(String username);
  8.  
    }

4.2 重点说明

这里采用的是SpringBoot的方式,所以相关的Service跟ServiceImpl省略,主要讲解多模块下的Security怎么运行登录跟认证。

下面的4.3就是多模块的关键文件,在Service模块下继承了UserDetailsService

4.3 MyUserDetailService

  1.  
    import com.Lino_white.model.User;
  2.  
    import com.Lino_white.service.UserService;
  3.  
    import com.Lino_white.spring_security.DiyUserDetails;
  4.  
    import org.springframework.beans.BeanUtils;
  5.  
    import org.springframework.beans.factory.annotation.Autowired;
  6.  
    import org.springframework.beans.factory.annotation.Qualifier;
  7.  
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
  8.  
    import org.springframework.security.core.userdetails.UserDetails;
  9.  
    import org.springframework.security.core.userdetails.UserDetailsService;
  10.  
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
  11.  
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  12.  
    import org.springframework.stereotype.Service;
  13.  
     
  14.  
    import java.util.ArrayList;
  15.  
    import java.util.List;
  16.  
     
  17.  
    /**
  18.  
    * 从数据库读取用户信息(用户名,密码,身份)进行身份认证
  19.  
    */
  20.  
    @Service("userDetailsService")
  21.  
    public class MyUserDetailService implements UserDetailsService {
  22.  
    @Autowired
  23.  
    private UserService userService;
  24.  
    @Override
  25.  
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  26.  
    System.out.println("********开始loadUserByUsername********");
  27.  
    User user = userService.findUserByName(username);
  28.  
    System.out.println("浏览器的username:" username);
  29.  
    System.out.println("数据库的username:" user.getUsername());
  30.  
    if (user==null) throw new UsernameNotFoundException(username);
  31.  
    //根据当前用户名查询用户权限
  32.  
    List<String> authorities=new ArrayList<>();
  33.  
    authorities.add("ROLE_" user.getIdentity());
  34.  
    DiyUserDetails details=new DiyUserDetails();
  35.  
    BeanUtils.copyProperties(user,details);
  36.  
    details.setAuthorities(authorities);
  37.  
    //如果数据库密码无加密,用下列
  38.  
    //details.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
  39.  
    System.out.println("********结束loadUserByUsername********");
  40.  
    return details;
  41.  
    }
  42.  
    }
学新通

5.spring_security模块

5.1 DiyUserDetails(UserDetails)

  1.  
    import com.Lino_white.model.User;
  2.  
    import lombok.Data;
  3.  
    import lombok.EqualsAndHashCode;
  4.  
    import org.springframework.security.core.GrantedAuthority;
  5.  
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
  6.  
    import org.springframework.security.core.userdetails.UserDetails;
  7.  
    import org.springframework.util.StringUtils;
  8.  
     
  9.  
    import java.io.Serializable;
  10.  
    import java.util.ArrayList;
  11.  
    import java.util.Collection;
  12.  
    @Data
  13.  
    @EqualsAndHashCode(callSuper = false)
  14.  
    public class DiyUserDetails extends User implements UserDetails, Serializable {
  15.  
     
  16.  
    //用户权限列表
  17.  
    private Collection<String> authorities;
  18.  
     
  19.  
    @Override
  20.  
    public Collection<? extends GrantedAuthority> getAuthorities() {
  21.  
    Collection<GrantedAuthority> authorities1 = new ArrayList<>();
  22.  
    for(String permissionValue : authorities) {
  23.  
    if(StringUtils.isEmpty(permissionValue)) continue;
  24.  
    SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
  25.  
    authorities1.add(authority);
  26.  
    }
  27.  
     
  28.  
    return authorities1;
  29.  
    }
  30.  
     
  31.  
    @Override
  32.  
    public boolean isAccountNonExpired() {
  33.  
    return true;
  34.  
    }
  35.  
     
  36.  
    @Override
  37.  
    public boolean isAccountNonLocked() {
  38.  
    return true;
  39.  
    }
  40.  
     
  41.  
    @Override
  42.  
    public boolean isCredentialsNonExpired() {
  43.  
    return true;
  44.  
    }
  45.  
     
  46.  
    @Override
  47.  
    public boolean isEnabled() {
  48.  
    return true;
  49.  
    }
  50.  
    }
学新通

5.2 WebSecurityConfig(WebSecurityConfigurerAdapter)

  1.  
    import com.Lino_white.spring_security.TokenAuthenticationFilter;
  2.  
    import com.Lino_white.spring_security.TokenLoginFilter;
  3.  
    import com.Lino_white.spring_security.TokenOncePerRequestFilter;
  4.  
    import com.Lino_white.spring_security.*;
  5.  
    import org.springframework.beans.factory.annotation.Autowired;
  6.  
    import org.springframework.context.annotation.Bean;
  7.  
    import org.springframework.context.annotation.Configuration;
  8.  
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  9.  
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  10.  
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  11.  
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
  12.  
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  13.  
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  14.  
    import org.springframework.security.config.http.SessionCreationPolicy;
  15.  
    import org.springframework.security.core.userdetails.UserDetailsService;
  16.  
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  17.  
    import org.springframework.security.crypto.password.PasswordEncoder;
  18.  
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  19.  
     
  20.  
    @Configuration
  21.  
    @EnableWebSecurity //开启Security功能
  22.  
    @EnableGlobalMethodSecurity(prePostEnabled = true) //启动方法级别的权限认证
  23.  
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  24.  
     
  25.  
    @Autowired
  26.  
    private UserDetailsService myUserDetailService;
  27.  
     
  28.  
    @Bean
  29.  
    //配置密码加密器
  30.  
    public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  31.  
     
  32.  
    //配置哪些请求不拦截
  33.  
    @Override
  34.  
    public void configure(WebSecurity web) throws Exception {
  35.  
    // web.ignoring().antMatchers("/index","/api/**");
  36.  
    }
  37.  
     
  38.  
    @Override
  39.  
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  40.  
    auth.userDetailsService(myUserDetailService).passwordEncoder(passwordEncoder());
  41.  
    }
  42.  
     
  43.  
    //配置安全策略
  44.  
    @Override
  45.  
    protected void configure(HttpSecurity http) throws Exception {
  46.  
    http.authorizeRequests()
  47.  
    .antMatchers("/index").authenticated()
  48.  
    .antMatchers("/user/**").authenticated()
  49.  
    .anyRequest().permitAll()
  50.  
    .and()
  51.  
    .addFilterBefore(new TokenOncePerRequestFilter(myUserDetailService), TokenLoginFilter.class)
  52.  
    //登录后,访问没有权限处理类
  53.  
    .exceptionHandling().accessDeniedHandler(new NothingAccessDeniedHandler())
  54.  
    //匿名访问,没有权限的处理类
  55.  
    .authenticationEntryPoint(new LoginAuthenticationEntryPoint())
  56.  
    //.anyRequest().authenticated()
  57.  
    .and()
  58.  
    .addFilter(new TokenLoginFilter(authenticationManager()))
  59.  
    .addFilter(new TokenAuthenticationFilter(authenticationManager()))
  60.  
    .formLogin()
  61.  
    .successHandler(new LoginInSuccessHandler())
  62.  
    .failureHandler(new LoginInFailHandler())
  63.  
    // 不需要session
  64.  
    .and()
  65.  
    .logout()
  66.  
    .logoutSuccessHandler(new LogOutSuccessHandler())
  67.  
    .and()
  68.  
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  69.  
    .and()
  70.  
    .csrf().disable()
  71.  
    ;
  72.  
    }
  73.  
    }
学新通

5.3 TokenAuthenticationFilter(BasicAuthenticationFilter)

  1.  
    import com.Lino_white.common.TokenUtil;
  2.  
    import org.springframework.security.authentication.AuthenticationManager;
  3.  
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  4.  
    import org.springframework.security.core.context.SecurityContextHolder;
  5.  
    import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
  6.  
     
  7.  
    import javax.servlet.FilterChain;
  8.  
    import javax.servlet.ServletException;
  9.  
    import javax.servlet.http.HttpServletRequest;
  10.  
    import javax.servlet.http.HttpServletResponse;
  11.  
    import java.io.IOException;
  12.  
    import java.util.ArrayList;
  13.  
     
  14.  
    public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
  15.  
    public TokenAuthenticationFilter(AuthenticationManager authenticationManager) {
  16.  
    super(authenticationManager);
  17.  
    }
  18.  
     
  19.  
    @Override
  20.  
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
  21.  
    String token = request.getHeader(TokenUtil.TOKEN_HEAD);
  22.  
    if (token==null || !token.startsWith(TokenUtil.TOKEN_PREFIX)){
  23.  
    // 如果请求头中没有Authorization信息则直接放行了
  24.  
    chain.doFilter(request,response);
  25.  
    return;
  26.  
    }
  27.  
    // 如果请求头中有token,则进行解析,并且设置认证信息
  28.  
    String usernameFromToken = new TokenUtil().getUsernameFromToken(token.replace(TokenUtil.TOKEN_PREFIX,""));
  29.  
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(usernameFromToken, null, new ArrayList<>());
  30.  
    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
  31.  
    super.doFilterInternal(request, response, chain);
  32.  
     
  33.  
    }
  34.  
    }
学新通

5.4 TokenLoginFilter(UsernamePasswordAuthenticationFilter)

  1.  
    import com.fasterxml.jackson.databind.ObjectMapper;
  2.  
    import com.Lino_white.model.User;
  3.  
    import com.Lino_white.spring_security.LoginInSuccessHandler;
  4.  
    import org.springframework.beans.factory.annotation.Autowired;
  5.  
    import org.springframework.security.authentication.AuthenticationManager;
  6.  
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  7.  
    import org.springframework.security.core.Authentication;
  8.  
    import org.springframework.security.core.AuthenticationException;
  9.  
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
  10.  
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  11.  
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
  12.  
    import org.springframework.stereotype.Component;
  13.  
     
  14.  
    import javax.servlet.FilterChain;
  15.  
    import javax.servlet.ServletException;
  16.  
    import javax.servlet.http.HttpServletRequest;
  17.  
    import javax.servlet.http.HttpServletResponse;
  18.  
    import java.io.IOException;
  19.  
    import java.io.PrintWriter;
  20.  
    import java.util.ArrayList;
  21.  
    import java.util.HashMap;
  22.  
    import java.util.List;
  23.  
    import java.util.Map;
  24.  
    /**
  25.  
    *
  26.  
    * 登录过滤器,继承UsernamePasswordAuthenticationFilter
  27.  
    * 对用户名密码进行登录校验,或对用户密码进行私钥解密等操作
  28.  
    *
  29.  
    */
  30.  
    public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
  31.  
     
  32.  
    private AuthenticationManager authenticationManager;
  33.  
     
  34.  
    public TokenLoginFilter(AuthenticationManager authenticationManager) {
  35.  
    this.authenticationManager = authenticationManager;
  36.  
    this.setPostOnly(false);
  37.  
     
  38.  
    // 认证路径 - 发送什么请求,就会进行认证
  39.  
    this.setRequiresAuthenticationRequestMatcher(
  40.  
    new AntPathRequestMatcher("/login", "POST")
  41.  
    );
  42.  
     
  43.  
    }
  44.  
     
  45.  
    @Override
  46.  
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
  47.  
    try {
  48.  
    String username = request.getParameter("username");
  49.  
    String password = request.getParameter("password");
  50.  
    System.out.println("进入UsernamePasswordAuthenticationFilter:username=" username " password=" password);
  51.  
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, password);
  52.  
    // usernamePasswordAuthenticationToken.setDetails(authenticationDetailsSource.buildDetails(request));
  53.  
    this.setDetails(request, usernamePasswordAuthenticationToken);
  54.  
    return authenticationManager.authenticate(usernamePasswordAuthenticationToken);
  55.  
    } catch (Exception e) {
  56.  
    throw new RuntimeException(e);
  57.  
    }
  58.  
    }
  59.  
     
  60.  
    @Override
  61.  
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
  62.  
    System.out.println("Filter认证成功------Start");
  63.  
    User user = (User) authResult.getPrincipal();
  64.  
    LoginInSuccessHandler loginInSuccessHandler = new LoginInSuccessHandler();
  65.  
    loginInSuccessHandler.onAuthenticationSuccess(request, response, chain, authResult);
  66.  
    System.out.println("Filter认证成功------End");
  67.  
    }
  68.  
     
  69.  
    @Override
  70.  
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
  71.  
    System.out.println("Filter认证失败------");
  72.  
    super.unsuccessfulAuthentication(request, response, failed);
  73.  
    }
  74.  
    }
学新通

5.5 TokenOncePerRequestFilter(OncePerRequestFilter)

  1.  
    import com.Lino_white.common.RedisUtil;
  2.  
    import com.Lino_white.common.ResponseUtil;
  3.  
    import com.Lino_white.common.TokenUtil;
  4.  
    import com.Lino_white.spring_security.DiyUserDetails;
  5.  
    import io.jsonwebtoken.Claims;
  6.  
    import io.jsonwebtoken.ExpiredJwtException;
  7.  
    import org.springframework.beans.factory.annotation.Autowired;
  8.  
    import org.springframework.beans.factory.annotation.Qualifier;
  9.  
    import org.springframework.data.redis.core.StringRedisTemplate;
  10.  
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  11.  
    import org.springframework.security.core.context.SecurityContextHolder;
  12.  
    import org.springframework.security.core.userdetails.UserDetails;
  13.  
    import org.springframework.security.core.userdetails.UserDetailsService;
  14.  
    import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
  15.  
    import org.springframework.stereotype.Component;
  16.  
    import org.springframework.web.filter.OncePerRequestFilter;
  17.  
    import sun.security.util.SecurityConstants;
  18.  
     
  19.  
    import javax.servlet.FilterChain;
  20.  
    import javax.servlet.ServletException;
  21.  
    import javax.servlet.http.HttpServletRequest;
  22.  
    import javax.servlet.http.HttpServletResponse;
  23.  
    import javax.xml.crypto.Data;
  24.  
    import java.io.IOException;
  25.  
    import java.text.ParseException;
  26.  
    import java.text.SimpleDateFormat;
  27.  
    import java.util.Date;
  28.  
     
  29.  
    /**
  30.  
    * 过滤器,在请求过来的时候,解析请求头中的token,再解析token得到用户信息,再存到SecurityContextHolder中
  31.  
    * @author Lino_white
  32.  
    */
  33.  
    @Component
  34.  
    public class TokenOncePerRequestFilter extends OncePerRequestFilter {
  35.  
    @Autowired
  36.  
    UserDetailsService userDetailsService;
  37.  
     
  38.  
    StringRedisTemplate stringRedisTemplate=RedisUtil.stringRedisTemplateStatic;
  39.  
     
  40.  
    public TokenOncePerRequestFilter(UserDetailsService myUserDetailService) {
  41.  
    userDetailsService=myUserDetailService;
  42.  
    }
  43.  
     
  44.  
    @Override
  45.  
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
  46.  
    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  47.  
    String authHeader = request.getHeader(TokenUtil.TOKEN_HEAD);
  48.  
     
  49.  
    if (authHeader != null && authHeader.startsWith(TokenUtil.TOKEN_PREFIX)) {
  50.  
     
  51.  
    final String authToken = authHeader.replace(TokenUtil.TOKEN_PREFIX,"");
  52.  
    //这里的authToken可能时间已过,需要重新创建一个token
  53.  
    //先对比redis中的过期时间,redis的过期时间随着用户的操作而更新,token可能没有及时更新
  54.  
    //进行判断,要么token失效了,跳转重新登录,
  55.  
    // 要么redis过期时间更新了,生成新的token返回给前端
  56.  
    String username;
  57.  
    Claims claims;
  58.  
    DiyUserDetails userDetails;
  59.  
    try {
  60.  
    claims = new TokenUtil().parseJwt(authToken);
  61.  
    username = claims.getSubject();
  62.  
    } catch (ExpiredJwtException e) {
  63.  
    //token过期
  64.  
    claims = e.getClaims();
  65.  
    username = claims.getSubject();
  66.  
    if (RedisUtil.hasToken(username)) {
  67.  
    Object expiration = stringRedisTemplate.opsForHash().get(username, "expiration");
  68.  
    Object tokenExpirationTime=f.format(claims.getExpiration());
  69.  
    Date expirationDate_redisTime=null,expirationDate_tokenTime=null,nowTime;
  70.  
    try {
  71.  
    expirationDate_redisTime= (Date) f.parseObject(String.valueOf(expiration));
  72.  
    expirationDate_tokenTime= (Date) f.parseObject(String.valueOf(tokenExpirationTime));
  73.  
    nowTime = (Date)f.parseObject(f.format(new Date()));
  74.  
    } catch (ParseException ex) {
  75.  
    throw new RuntimeException(ex);
  76.  
    }
  77.  
     
  78.  
    System.out.println("*********Token过期(Start)***********");
  79.  
    System.out.println("token浏览器过期时间:" tokenExpirationTime);
  80.  
     
  81.  
    System.out.println("redis过期时间:" expiration);
  82.  
     
  83.  
    /*
  84.  
    * redis<token || token=redis || redis <now 则token失效,跳转登录
  85.  
    * token<redis
  86.  
    * */
  87.  
    if (expirationDate_redisTime.getTime() < expirationDate_tokenTime.getTime() ||
  88.  
    expirationDate_tokenTime.getTime() == expirationDate_redisTime.getTime() ||
  89.  
    expirationDate_redisTime.getTime() < nowTime.getTime()) {
  90.  
     
  91.  
    //时间相同,跳转登录
  92.  
    ResponseUtil.reponseOutDiy(response, 401, "用户已过期,请重新登录");
  93.  
    System.out.println("*********Token过期(End)失效***********");
  94.  
    return;
  95.  
    } else {
  96.  
    //时间不同,生成新token 需要用户id,身份,用户名
  97.  
    //response存入token 返回
  98.  
    Object expiration_redisTime = stringRedisTemplate.opsForHash().get(username, "expiration");
  99.  
     
  100.  
     
  101.  
    Date date;
  102.  
    try {
  103.  
    date = (Date) f.parseObject(String.valueOf(expiration_redisTime));
  104.  
    } catch (ParseException ex) {
  105.  
    throw new RuntimeException(ex);
  106.  
    }
  107.  
    //通过数据库查询数据,创建token
  108.  
    userDetails = (DiyUserDetails) userDetailsService.loadUserByUsername(username);
  109.  
    String token = TokenUtil.createToken(userDetails,date);
  110.  
    System.out.println("—————————————————start—————————————————————");
  111.  
    System.out.println("token:" token);
  112.  
    RedisUtil.redis_SaveTokenInfo(token,username);
  113.  
    response.setHeader(TokenUtil.TOKEN_HEAD,TokenUtil.TOKEN_PREFIX token);
  114.  
    request.setAttribute(TokenUtil.TOKEN_HEAD,TokenUtil.TOKEN_PREFIX token);
  115.  
    Date expiration1 = new TokenUtil().parseJwt(token).getExpiration();
  116.  
    System.out.println("重新更新token后过期时间:" expiration1);
  117.  
    System.out.println("—————————————————End—————————————————————");
  118.  
    ResponseUtil.reponseOutDiy(response, 200, token);
  119.  
    System.out.println("*********Token过期(End)新Token***********");
  120.  
    return;
  121.  
    }
  122.  
    }
  123.  
    }
  124.  
     
  125.  
     
  126.  
    if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
  127.  
    System.out.println("OncePerRequestFilter 中的username :" username);
  128.  
    userDetails = (DiyUserDetails) userDetailsService.loadUserByUsername(username);
  129.  
    if (userDetails != null) {
  130.  
    UsernamePasswordAuthenticationToken authentication =
  131.  
    new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
  132.  
    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
  133.  
    SecurityContextHolder.getContext().setAuthentication(authentication);
  134.  
    }
  135.  
    }
  136.  
    }
  137.  
    chain.doFilter(request, response);
  138.  
    }
  139.  
    }
学新通

5.6 LoginAuthenticationEntryPoint(AuthenticationEntryPoint)

  1.  
    import com.Lino_white.common.ResponseUtil;
  2.  
    import com.Lino_white.common.TokenUtil;
  3.  
    import jdk.nashorn.internal.parser.Token;
  4.  
    import org.springframework.security.core.AuthenticationException;
  5.  
    import org.springframework.security.web.AuthenticationEntryPoint;
  6.  
    import org.springframework.stereotype.Component;
  7.  
     
  8.  
    import javax.servlet.ServletException;
  9.  
    import javax.servlet.http.HttpServletRequest;
  10.  
    import javax.servlet.http.HttpServletResponse;
  11.  
    import java.io.IOException;
  12.  
    /**
  13.  
    * 匿名未登录的时候访问,需要登录的资源的调用类
  14.  
    * @author Lino_white
  15.  
    */
  16.  
    @Component
  17.  
    public class LoginAuthenticationEntryPoint implements AuthenticationEntryPoint {
  18.  
    @Override
  19.  
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
  20.  
    String token =httpServletRequest.getHeader(TokenUtil.TOKEN_HEAD);
  21.  
    System.out.println("当前未登录,无法访问 ::" token);
  22.  
    if (token!=null && token.contains(TokenUtil.TOKEN_PREFIX)) {
  23.  
    token=token.replace(TokenUtil.TOKEN_PREFIX,"");
  24.  
    String usernameFromToken = new TokenUtil().getUsernameFromToken(token);
  25.  
    System.out.println("用户名:" usernameFromToken);
  26.  
    }
  27.  
    ResponseUtil.reponseOutDiy(httpServletResponse,401,"当前未登录,无法访问");
  28.  
    }
  29.  
    }
学新通

5.7 LoginInFailHandler(AuthenticationFailureHandler)

  1.  
    import com.Lino_white.common.ResponseUtil;
  2.  
    import org.springframework.security.core.AuthenticationException;
  3.  
    import org.springframework.security.web.authentication.AuthenticationFailureHandler;
  4.  
    import org.springframework.stereotype.Component;
  5.  
     
  6.  
    import javax.servlet.ServletException;
  7.  
    import javax.servlet.http.HttpServletRequest;
  8.  
    import javax.servlet.http.HttpServletResponse;
  9.  
    import java.io.IOException;
  10.  
    /**
  11.  
    * 登录账号密码错误等情况下,会调用的处理类
  12.  
    * @author Lino_white
  13.  
    */
  14.  
    @Component
  15.  
    public class LoginInFailHandler implements AuthenticationFailureHandler {
  16.  
    @Override
  17.  
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
  18.  
    System.out.println("认证失败————————————");
  19.  
    ResponseUtil.reponseOutDiy(httpServletResponse,401,"登录失败,请重试");
  20.  
    }
  21.  
    }
学新通

5.8 LoginInSuccessHandler(AuthenticationSuccessHandler)

  1.  
     
  2.  
    import com.fasterxml.jackson.databind.ObjectMapper;
  3.  
    import com.Lino_white.common.RedisUtil;
  4.  
    import com.Lino_white.common.ResponseUtil;
  5.  
    import com.Lino_white.common.TokenUtil;
  6.  
    import com.Lino_white.model.User;
  7.  
    import org.springframework.beans.factory.annotation.Autowired;
  8.  
    import org.springframework.data.redis.core.StringRedisTemplate;
  9.  
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  10.  
    import org.springframework.security.core.Authentication;
  11.  
    import org.springframework.security.core.context.SecurityContextHolder;
  12.  
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
  13.  
    import org.springframework.stereotype.Component;
  14.  
     
  15.  
    import javax.annotation.PostConstruct;
  16.  
    import javax.servlet.FilterChain;
  17.  
    import javax.servlet.ServletException;
  18.  
    import javax.servlet.http.HttpServletRequest;
  19.  
    import javax.servlet.http.HttpServletResponse;
  20.  
    import java.io.IOException;
  21.  
    import java.io.PrintWriter;
  22.  
    import java.time.LocalDateTime;
  23.  
    import java.util.HashMap;
  24.  
    import java.util.Map;
  25.  
    /**
  26.  
    * 登录成功处理类,登录成功后会调用里面的方法
  27.  
    * @author Lino_white
  28.  
    */
  29.  
    @Component
  30.  
    public class LoginInSuccessHandler implements AuthenticationSuccessHandler {
  31.  
    /**
  32.  
    * 用户通过TokenLoginFilter(UsernamePasswordAuthenticationFilter)后,
  33.  
    * 验证成功到这里进行 token创建,并将其存入redis
  34.  
    *
  35.  
    */
  36.  
    @Override
  37.  
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
  38.  
    User user =(User) authentication.getPrincipal();
  39.  
    String token = TokenUtil.createToken(user);
  40.  
     
  41.  
    //redis缓存token
  42.  
    RedisUtil.redis_SaveTokenInfo(token,user.getUsername());
  43.  
     
  44.  
    //写入response
  45.  
    response.setHeader("token", TokenUtil.TOKEN_PREFIX token);
  46.  
     
  47.  
    try {
  48.  
    //登录成功,返回json格式进行提示
  49.  
    response.setContentType("application/json;charset=utf-8");
  50.  
    response.setStatus(HttpServletResponse.SC_OK);
  51.  
    PrintWriter out=response.getWriter();
  52.  
    Map<String,Object> map=new HashMap<String,Object>(4);
  53.  
    map.put("code",HttpServletResponse.SC_OK);
  54.  
    map.put("message","登录成功");
  55.  
    out.write(new ObjectMapper().writeValueAsString(map));
  56.  
    out.flush();
  57.  
    out.close();
  58.  
    }catch (Exception e){
  59.  
    e.printStackTrace();
  60.  
    }
  61.  
    response.setStatus(200);
  62.  
    chain.doFilter(request, response);
  63.  
    }
  64.  
     
  65.  
    @Override
  66.  
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
  67.  
     
  68.  
    }
  69.  
     
  70.  
    }
学新通

5.9 LogOutSuccessHandler(LogoutSuccessHandler)

  1.  
    import com.Lino_white.common.RedisUtil;
  2.  
    import com.Lino_white.common.ResponseUtil;
  3.  
    import com.Lino_white.common.TokenUtil;
  4.  
    import org.springframework.data.redis.core.StringRedisTemplate;
  5.  
    import org.springframework.security.core.Authentication;
  6.  
    import org.springframework.security.core.context.SecurityContextHolder;
  7.  
    import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
  8.  
    import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
  9.  
    import org.springframework.stereotype.Component;
  10.  
     
  11.  
    import javax.servlet.ServletException;
  12.  
    import javax.servlet.http.HttpServletRequest;
  13.  
    import javax.servlet.http.HttpServletResponse;
  14.  
    import java.io.IOException;
  15.  
     
  16.  
    @Component
  17.  
    public class LogOutSuccessHandler implements LogoutSuccessHandler {
  18.  
    private StringRedisTemplate stringRedisTemplate= RedisUtil.stringRedisTemplateStatic;
  19.  
    @Override
  20.  
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
  21.  
    //用户退出登录
  22.  
    System.out.println("LogoutSuccessHandler退出");
  23.  
    String token=request.getHeader("token");
  24.  
    if (token==null) token=request.getHeader(TokenUtil.TOKEN_HEAD);
  25.  
    token=token.replace(TokenUtil.TOKEN_PREFIX,"");
  26.  
    String username = new TokenUtil().getUsernameFromToken(token);
  27.  
    Authentication au = SecurityContextHolder.getContext().getAuthentication();
  28.  
    if (au!=null) new SecurityContextLogoutHandler().logout(request,response,au);
  29.  
    Boolean delete = stringRedisTemplate.delete(username);
  30.  
    if (delete) ResponseUtil.reponseOutDiy(response,200,"用户已成功退出");
  31.  
    }
  32.  
    }
学新通

5.10 NothingAccessDeniedHandler(AccessDeniedHandler)

  1.  
    import com.Lino_white.common.ResponseUtil;
  2.  
    import org.springframework.security.access.AccessDeniedException;
  3.  
    import org.springframework.security.web.access.AccessDeniedHandler;
  4.  
    import org.springframework.stereotype.Component;
  5.  
     
  6.  
    import javax.servlet.ServletException;
  7.  
    import javax.servlet.http.HttpServletRequest;
  8.  
    import javax.servlet.http.HttpServletResponse;
  9.  
    import java.io.IOException;
  10.  
    /**
  11.  
    * 没有权限,被拒绝访问时的调用类
  12.  
    * @author Lino_white
  13.  
    */
  14.  
    @Component
  15.  
    public class NothingAccessDeniedHandler implements AccessDeniedHandler {
  16.  
    @Override
  17.  
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
  18.  
    System.out.println("没有权限");
  19.  
    ResponseUtil.reponseOutDiy(httpServletResponse,403,"当前您没有该权限");
  20.  
    }
  21.  
    }
学新通

6.测试

这里是使用postman工具进行测试的,在这里之前已经在数据库有用户名跟密码都为user的数据,并且密码已是加密形式。

1.首次访问index,如下图

学新通

2.访问/login,并且提供相关参数,如下图:

学新通

这时,redis数据库就有了用户名为 user的数据 

学新通

3.在返回Headers信息中找到token,复制除了Bearer 空格以外的东西,如下图的蓝色底token

学新通

4.将请求方式改成Get,在Authorization的Type中,选择Bearer Token,粘贴上刚才的Token,点击Send发送

学新通

 5.就会显示可以正常访问index页面了

学新通

6.退出则为/logout ,带上参数username即可,请求方式为POST。

学新通

 同时,redis数据库中用户名为user的key值也被删除掉。

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfhgckb
系列文章
更多 icon
同类精品
更多 icon
继续加载