0


Spring-Security实现登录接口

目录

简介

Security

Spring

家族中的一个安全管理框架。相比与另外一个安全框架

Shiro

,它提供了更丰富的功能,社区资源也比Shiro丰富。

具体介绍和入门看springSecurity入门

原理初探

在实现之前幺要了解一下登录校验的流程以及

SpringSecurity

的原理以及认证流程

1、登录校验流程
在这里插入图片描述

2、 SpringSecurity完整流程

SpringSecurity

的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。这里我们可以看看入门案例中的过滤器。
在这里插入图片描述
图中只展示了核心过滤器,其它的非核心过滤器并没有在图中展示。

UsernamePasswordAuthenticationFilter:负责处理我们在登陆页面填写了用户名密码后的登陆请求。入门案例的认证工作主要有它负责。

ExceptionTranslationFilter:处理过滤器链中抛出的任何

AccessDeniedException

AuthenticationException

FilterSecurityInterceptor:负责权限校验的过滤器。

我们可以通过

Debug

查看当前系统中

SpringSecurity

过滤器链中有哪些过滤器及它们的顺序。
在这里插入图片描述

3、认证流程
在这里插入图片描述
概念速查:

  • Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。
  • AuthenticationManager接口:定义了认证Authentication的方法
  • UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。
  • UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。

实现思路

登录

​ ①自定义登录接口

​ 调用

ProviderManager

的方法进行认证 如果认证通过生成

jwt

​ 把用户信息存入

redis

​ ②自定义

UserDetailsService

​ 在这个实现类中去查询数据库

校验:

​ ①定义Jwt认证过滤器

​ 获取

token

​ 解析

token

获取其中的

userid

​ 从

redis

中获取用户信息

​ 存入

SecurityContextHolder

这里我们主要是实现登录接口的功能
核心思想就是就是将

认证流程

中的

UserDetailsService

重写其

loadUserByUsername

的方法,使其从数据库中查询数据,然后用自己的类(我这里是

UserLogin

)实现

UserDetails

,在

loadUserByUsername

中返回

UserLogin

登录接口实现

准备工作

添加依赖,添加工具类,创建数据库,编写配置文件
1、添加依赖

<!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--fastjson依赖--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.33</version></dependency><!--jwt依赖--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>

2、添加Redis相关配置

importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.serializer.SerializerFeature;importcom.fasterxml.jackson.databind.JavaType;importcom.fasterxml.jackson.databind.ObjectMapper;importcom.fasterxml.jackson.databind.type.TypeFactory;importorg.springframework.data.redis.serializer.RedisSerializer;importorg.springframework.data.redis.serializer.SerializationException;importcom.alibaba.fastjson.parser.ParserConfig;importorg.springframework.util.Assert;importjava.nio.charset.Charset;/**
 * Redis使用FastJson序列化
 * 
 * @author sg
 */publicclassFastJsonRedisSerializer<T>implementsRedisSerializer<T>{publicstaticfinalCharsetDEFAULT_CHARSET=Charset.forName("UTF-8");privateClass<T> clazz;static{ParserConfig.getGlobalInstance().setAutoTypeSupport(true);}publicFastJsonRedisSerializer(Class<T> clazz){super();this.clazz = clazz;}@Overridepublicbyte[]serialize(T t)throwsSerializationException{if(t ==null){returnnewbyte[0];}returnJSON.toJSONString(t,SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);}@OverridepublicTdeserialize(byte[] bytes)throwsSerializationException{if(bytes ==null|| bytes.length <=0){returnnull;}String str =newString(bytes,DEFAULT_CHARSET);returnJSON.parseObject(str, clazz);}protectedJavaTypegetJavaType(Class<?> clazz){returnTypeFactory.defaultInstance().constructType(clazz);}}
importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.StringRedisSerializer;@ConfigurationpublicclassRedisConfig{@Bean@SuppressWarnings(value ={"unchecked","rawtypes"})publicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactory connectionFactory){RedisTemplate<Object,Object> template =newRedisTemplate<>();
        template.setConnectionFactory(connectionFactory);FastJsonRedisSerializer serializer =newFastJsonRedisSerializer(Object.class);// 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(newStringRedisSerializer());
        template.setValueSerializer(serializer);// Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(newStringRedisSerializer());
        template.setHashValueSerializer(serializer);

        template.afterPropertiesSet();return template;}}

封装返回的数据

importcom.fasterxml.jackson.annotation.JsonInclude;@JsonInclude(JsonInclude.Include.NON_NULL)publicclassResponseResult<T>{/**
     * 状态码
     */privateInteger code;/**
     * 提示信息,如果有错误时,前端可以获取该字段进行提示
     */privateString msg;/**
     * 查询到的结果数据,
     */privateT data;publicResponseResult(Integer code,String msg){this.code = code;this.msg = msg;}publicResponseResult(Integer code,T data){this.code = code;this.data = data;}publicIntegergetCode(){return code;}publicvoidsetCode(Integer code){this.code = code;}publicStringgetMsg(){return msg;}publicvoidsetMsg(String msg){this.msg = msg;}publicTgetData(){return data;}publicvoidsetData(T data){this.data = data;}publicResponseResult(Integer code,String msg,T data){this.code = code;this.msg = msg;this.data = data;}}

JWT工具类

importio.jsonwebtoken.Claims;importio.jsonwebtoken.JwtBuilder;importio.jsonwebtoken.Jwts;importio.jsonwebtoken.SignatureAlgorithm;importjavax.crypto.SecretKey;importjavax.crypto.spec.SecretKeySpec;importjava.util.Base64;importjava.util.Date;importjava.util.UUID;/**
 * JWT工具类
 */publicclassJwtUtil{//有效期为publicstaticfinalLongJWT_TTL=60*60*1000L;// 60 * 60 *1000  一个小时//设置秘钥明文publicstaticfinalStringJWT_KEY="sangeng";publicstaticStringgetUUID(){String token =UUID.randomUUID().toString().replaceAll("-","");return token;}/**
     * 生成jtw
     * @param subject token中要存放的数据(json格式)
     * @return
     */publicstaticStringcreateJWT(String subject){JwtBuilder builder =getJwtBuilder(subject,null,getUUID());// 设置过期时间return builder.compact();}/**
     * 生成jtw
     * @param subject token中要存放的数据(json格式)
     * @param ttlMillis token超时时间
     * @return
     */publicstaticStringcreateJWT(String subject,Long ttlMillis){JwtBuilder builder =getJwtBuilder(subject, ttlMillis,getUUID());// 设置过期时间return builder.compact();}privatestaticJwtBuildergetJwtBuilder(String subject,Long ttlMillis,String uuid){SignatureAlgorithm signatureAlgorithm =SignatureAlgorithm.HS256;SecretKey secretKey =generalKey();long nowMillis =System.currentTimeMillis();Date now =newDate(nowMillis);if(ttlMillis==null){
            ttlMillis=JwtUtil.JWT_TTL;}long expMillis = nowMillis + ttlMillis;Date expDate =newDate(expMillis);returnJwts.builder().setId(uuid)//唯一的ID.setSubject(subject)// 主题  可以是JSON数据.setIssuer("sg")// 签发者.setIssuedAt(now)// 签发时间.signWith(signatureAlgorithm, secretKey)//使用HS256对称加密算法签名, 第二个参数为秘钥.setExpiration(expDate);}/**
     * 创建token
     * @param id
     * @param subject
     * @param ttlMillis
     * @return
     */publicstaticStringcreateJWT(String id,String subject,Long ttlMillis){JwtBuilder builder =getJwtBuilder(subject, ttlMillis, id);// 设置过期时间return builder.compact();}publicstaticvoidmain(String[] args)throwsException{String token ="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg";Claims claims =parseJWT(token);System.out.println(claims);}/**
     * 生成加密后的秘钥 secretKey
     * @return
     */publicstaticSecretKeygeneralKey(){byte[] encodedKey =Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey key =newSecretKeySpec(encodedKey,0, encodedKey.length,"AES");return key;}/**
     * 解析
     *
     * @param jwt
     * @return
     * @throws Exception
     */publicstaticClaimsparseJWT(String jwt)throwsException{SecretKey secretKey =generalKey();returnJwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}}

Redis工具类

importjava.util.*;importjava.util.concurrent.TimeUnit;@SuppressWarnings(value ={"unchecked","rawtypes"})@ComponentpublicclassRedisCache{@AutowiredpublicRedisTemplate redisTemplate;/**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     */public<T>voidsetCacheObject(finalString key,finalT value){
        redisTemplate.opsForValue().set(key, value);}/**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     * @param timeout 时间
     * @param timeUnit 时间颗粒度
     */public<T>voidsetCacheObject(finalString key,finalT value,finalInteger timeout,finalTimeUnit timeUnit){
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);}/**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @return true=设置成功;false=设置失败
     */publicbooleanexpire(finalString key,finallong timeout){returnexpire(key, timeout,TimeUnit.SECONDS);}/**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @param unit 时间单位
     * @return true=设置成功;false=设置失败
     */publicbooleanexpire(finalString key,finallong timeout,finalTimeUnit unit){return redisTemplate.expire(key, timeout, unit);}/**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */public<T>TgetCacheObject(finalString key){ValueOperations<String,T> operation = redisTemplate.opsForValue();return operation.get(key);}/**
     * 删除单个对象
     *
     * @param key
     */publicbooleandeleteObject(finalString key){return redisTemplate.delete(key);}/**
     * 删除集合对象
     *
     * @param collection 多个对象
     * @return
     */publiclongdeleteObject(finalCollection collection){return redisTemplate.delete(collection);}/**
     * 缓存List数据
     *
     * @param key 缓存的键值
     * @param dataList 待缓存的List数据
     * @return 缓存的对象
     */public<T>longsetCacheList(finalString key,finalList<T> dataList){Long count = redisTemplate.opsForList().rightPushAll(key, dataList);return count ==null?0: count;}/**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */public<T>List<T>getCacheList(finalString key){return redisTemplate.opsForList().range(key,0,-1);}/**
     * 缓存Set
     *
     * @param key 缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */public<T>BoundSetOperations<String,T>setCacheSet(finalString key,finalSet<T> dataSet){BoundSetOperations<String,T> setOperation = redisTemplate.boundSetOps(key);Iterator<T> it = dataSet.iterator();while(it.hasNext()){
            setOperation.add(it.next());}return setOperation;}/**
     * 获得缓存的set
     *
     * @param key
     * @return
     */public<T>Set<T>getCacheSet(finalString key){return redisTemplate.opsForSet().members(key);}/**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     */public<T>voidsetCacheMap(finalString key,finalMap<String,T> dataMap){if(dataMap !=null){
            redisTemplate.opsForHash().putAll(key, dataMap);}}/**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */public<T>Map<String,T>getCacheMap(finalString key){return redisTemplate.opsForHash().entries(key);}/**
     * 往Hash中存入数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @param value 值
     */public<T>voidsetCacheMapValue(finalString key,finalString hKey,finalT value){
        redisTemplate.opsForHash().put(key, hKey, value);}/**
     * 获取Hash中的数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */public<T>TgetCacheMapValue(finalString key,finalString hKey){HashOperations<String,String,T> opsForHash = redisTemplate.opsForHash();return opsForHash.get(key, hKey);}/**
     * 删除Hash中的数据
     * 
     * @param key
     * @param hkey
     */publicvoiddelCacheMapValue(finalString key,finalString hkey){HashOperations hashOperations = redisTemplate.opsForHash();
        hashOperations.delete(key, hkey);}/**
     * 获取多个Hash中的数据
     *
     * @param key Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */public<T>List<T>getMultiCacheMapValue(finalString key,finalCollection<Object> hKeys){return redisTemplate.opsForHash().multiGet(key, hKeys);}/**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */publicCollection<String>keys(finalString pattern){return redisTemplate.keys(pattern);}}

将字符串渲染到客户端工具类

importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;publicclassWebUtils{/**
     * 将字符串渲染到客户端
     * 
     * @param response 渲染对象
     * @param string 待渲染的字符串
     * @return null
     */publicstaticStringrenderString(HttpServletResponse response,String string){try{
            response.setStatus(200);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);}catch(IOException e){
            e.printStackTrace();}returnnull;}}

SQL语句创建用户表

CREATETABLE `sys_user` (
  `id` BIGINT(20)NOTNULLAUTO_INCREMENTCOMMENT'主键',
  `user_name` VARCHAR(64)NOTNULLDEFAULT'NULL'COMMENT'用户名',
  `nick_name` VARCHAR(64)NOTNULLDEFAULT'NULL'COMMENT'昵称',
  `password` VARCHAR(64)NOTNULLDEFAULT'NULL'COMMENT'密码',
  `status` CHAR(1)DEFAULT'0'COMMENT '账号状态(0正常 1停用)',
  `email` VARCHAR(64)DEFAULTNULLCOMMENT'邮箱',
  `phonenumber` VARCHAR(32)DEFAULTNULLCOMMENT'手机号',
  `sex` CHAR(1)DEFAULTNULLCOMMENT '用户性别(0男,1女,2未知)',
  `avatar` VARCHAR(128)DEFAULTNULLCOMMENT'头像',
  `user_type` CHAR(1)NOTNULLDEFAULT'1'COMMENT '用户类型(0管理员,1普通用户)',
  `create_by` BIGINT(20)DEFAULTNULLCOMMENT '创建人的用户id',
  `create_time` DATETIMEDEFAULTNULLCOMMENT'创建时间',
  `update_by` BIGINT(20)DEFAULTNULLCOMMENT'更新人',
  `update_time` DATETIMEDEFAULTNULLCOMMENT'更新时间',
  `del_flag` INT(11)DEFAULT'0'COMMENT '删除标志(0代表未删除,1代表已删除)',PRIMARYKEY(`id`))ENGINE=INNODBAUTO_INCREMENT=2DEFAULTCHARSET=utf8mb4 COMMENT='用户表'

配置文件

spring:
  datasource:
    driver-class-name:com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/你的数据库名称?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
    username:****
    password:****
  redis:
    # Redis服务器地址
    host:127.0.0.1
    # Redis服务器连接端口
    port:6379
    # Redis服务器连接密码
    password:
    # Redis数据库索引
    database:3
    # 连接超时时间(毫秒)
    timeout:30000
    lettuce:
      pool:
        max-active:50
        max-wait:-1
        max-idle:50
        min-idle:1

编码实现

目录结构
关于

Email

的类不用管
在这里插入图片描述
配置类
RedisConfig类

packagecom.zzuli.common.config;importcom.zzuli.common.utils.FastJsonRedisSerializer;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.StringRedisSerializer;publicclassRedisConfig{publicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactory connectionFactory){RedisTemplate<Object,Object> template =newRedisTemplate<>();
        template.setConnectionFactory(connectionFactory);FastJsonRedisSerializer serializer =newFastJsonRedisSerializer(Object.class);// 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(newStringRedisSerializer());
        template.setValueSerializer(serializer);// Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(newStringRedisSerializer());
        template.setHashValueSerializer(serializer);

        template.afterPropertiesSet();return template;}}
SecurityConfig

packagecom.zzuli.common.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.authentication.AuthenticationManager;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.config.http.SessionCreationPolicy;importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;importorg.springframework.security.crypto.password.PasswordEncoder;/**
 * @author niuben
 */@ConfigurationpublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{//创建BCryptPasswordEncoder注入容器@BeanpublicPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{
        http
                //关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers("/user/login").anonymous()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();}@Bean@OverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}}

实体类

User类
packagecom.zzuli.pojo;importcom.baomidou.mybatisplus.annotation.TableId;importcom.baomidou.mybatisplus.annotation.TableName;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.io.Serializable;importjava.util.Date;/**
 * 用户表(User)实体类
 *
 * @author 三更
 */@Data@AllArgsConstructor@NoArgsConstructor@TableName("sys_user")//数据库的用户名名称publicclassUserimplementsSerializable{privatestaticfinallong serialVersionUID =-40356785423868312L;/**
    * 主键
    */@TableIdprivateLong id;/**
    * 用户名
    */privateString userName;/**
    * 昵称
    */privateString nickName;/**
    * 密码
    */privateString password;/**
    * 账号状态(0正常 1停用)
    */privateString status;/**
    * 邮箱
    */privateString email;/**
    * 手机号
    */privateString phonenumber;/**
    * 用户性别(0男,1女,2未知)
    */privateString sex;/**
    * 头像
    */privateString avatar;/**
    * 用户类型(0管理员,1普通用户)
    */privateString userType;/**
    * 创建人的用户id
    */privateLong createBy;/**
    * 创建时间
    */privateDate createTime;/**
    * 更新人
    */privateLong updateBy;/**
    * 更新时间
    */privateDate updateTime;/**
    * 删除标志(0代表未删除,1代表已删除)
    */privateInteger delFlag;}
UserLogin


继承

UserDetails
packagecom.zzuli.pojo;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importorg.springframework.security.core.GrantedAuthority;importorg.springframework.security.core.userdetails.UserDetails;importjava.util.Collection;/**
 * @author niuben
 */@AllArgsConstructor@NoArgsConstructor@DatapublicclassUserLoginimplementsUserDetails{privateUser user;@OverridepublicCollection<?extendsGrantedAuthority>getAuthorities(){returnnull;}@OverridepublicStringgetPassword(){return user.getPassword();}@OverridepublicStringgetUsername(){return user.getUserName();}@OverridepublicbooleanisAccountNonExpired(){returntrue;}@OverridepublicbooleanisAccountNonLocked(){returntrue;}@OverridepublicbooleanisCredentialsNonExpired(){returntrue;}@OverridepublicbooleanisEnabled(){returntrue;}}

接口实现类

LoginController

接口

packagecom.zzuli.controller;importcom.zzuli.common.api.CommonResult;importcom.zzuli.pojo.User;importcom.zzuli.service.LoginService;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestBody;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.annotation.Resource;/**
 * @author niuben
 */@RestControllerpublicclassLoginController{@ResourceprivateLoginService loginService;@PostMapping("/user/login")publicCommonResult<Object>login(@RequestBodyUser user){CommonResult<Object> result =null;try{
            result = loginService.login(user);}catch(Exception e){returnCommonResult.success("账户或者密码错误!");}return result;}}
UserDetailsServiceImpl

实现类

packagecom.zzuli.service.impl;importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;importcom.zzuli.mapper.UserMapper;importcom.zzuli.pojo.User;importcom.zzuli.pojo.UserLogin;importorg.springframework.security.core.userdetails.UserDetails;importorg.springframework.security.core.userdetails.UserDetailsService;importorg.springframework.security.core.userdetails.UsernameNotFoundException;importorg.springframework.stereotype.Service;importjavax.annotation.Resource;importjava.util.Objects;/**
 * @author niuben
 */@ServicepublicclassUserDetailsServiceImplimplementsUserDetailsService{@ResourceprivateUserMapper userMapper;@OverridepublicUserDetailsloadUserByUsername(String username)throwsUsernameNotFoundException{//查询用户信息LambdaQueryWrapper<User> queryWrapper =newLambdaQueryWrapper<User>();
        queryWrapper.eq(User::getUserName,username);User user = userMapper.selectOne(queryWrapper);//如果没有查询到用户,就抛出异常if(Objects.isNull(user)){thrownewRuntimeException("用户名或者密码错误!");}//将数据封装成UserDetailsreturnnewUserLogin(user);}}
LoginService

接口

packagecom.zzuli.service;importcom.zzuli.common.api.CommonResult;importcom.zzuli.pojo.User;/**
 * @author niuben
 */publicinterfaceLoginService{CommonResult<Object>login(User user);}
LoginService

实现接口

packagecom.zzuli.service.impl;importcom.zzuli.common.api.CommonResult;importcom.zzuli.common.utils.JwtUtil;importcom.zzuli.common.utils.RedisCache;importcom.zzuli.pojo.User;importcom.zzuli.pojo.UserLogin;importcom.zzuli.service.LoginService;importorg.springframework.security.authentication.AuthenticationManager;importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;importorg.springframework.security.core.Authentication;importorg.springframework.stereotype.Service;importjavax.annotation.Resource;importjava.util.HashMap;importjava.util.Map;importjava.util.Objects;/**
 * @author niuben
 */@ServicepublicclassLoginServiceImplimplementsLoginService{@ResourceprivateAuthenticationManager authenticationManager;@ResourceprivateRedisCache redisCache;@OverridepublicCommonResult<Object>login(User user){//进行用户认证UsernamePasswordAuthenticationToken authenticationToken =newUsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());Authentication authenticate = authenticationManager.authenticate(authenticationToken);//认证未通过,给出提示if(Objects.isNull(authenticate)){thrownewRuntimeException("登陆失败!");}//通过了,生成jwtUserLogin loginUser =(UserLogin) authenticate.getPrincipal();String id = loginUser.getUser().getId().toString();String jwt =JwtUtil.createJWT(id);Map<String,String> map =newHashMap<>();
        map.put("token",jwt);//将用户信息存入redis
        redisCache.setCacheObject("login"+id,loginUser);returnCommonResult.success(map,"登陆成功!");}}
UserMapper

packagecom.zzuli.mapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.zzuli.pojo.User;publicinterfaceUserMapperextendsBaseMapper<User>{}

启动类

packagecom.zzuli;importorg.apache.ibatis.annotations.Mapper;importorg.mybatis.spring.annotation.MapperScan;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@MapperScan("com.zzuli.mapper")//mapper扫描器publicclassAppleunlockManageApplication{publicstaticvoidmain(String[] args){SpringApplication.run(AppleunlockManageApplication.class, args);}}

效果展示

注意:测试时要打开

redis

,数据库中的密码必须是加密后的
可以使用一下方法进行加密,

passwordEncoder

SecurityConfig

中已经注入的

@ResourceprivatePasswordEncoder passwordEncoder;String encode = passwordEncoder.encode("123456");System.out.println(encode);

在这里插入图片描述
登录接口测试
在这里插入图片描述

标签: spring java 前端

本文转载自: https://blog.csdn.net/niulinbiao/article/details/128881220
版权归原作者 韭菜盖饭 所有, 如有侵权,请联系我们删除。

“Spring-Security实现登录接口”的评论:

还没有评论