当前位置: 首页 > news >正文

怎样优化排名自己网站会计培训班

怎样优化排名自己网站,会计培训班,小游戏网站怎么做建站,晋江网站建设价格文章目录登陆校验流程依赖yaml实现建表、工具类、实体类加密器、AuthenticationManager登录逻辑登录过滤器、配置过滤器登出登陆校验流程 认证 登录: ​ ①自定义登录接口 ​ 调用ProviderManager的方法进行认证 如果认证通过生成token,根据userId把用…

文章目录

  • 登陆校验流程
  • 依赖
  • yaml
  • 实现
    • 建表、工具类、实体类
    • 加密器、AuthenticationManager
    • 登录逻辑
    • 登录过滤器、配置过滤器
    • 登出

登陆校验流程

认证
在这里插入图片描述
在这里插入图片描述
登录:
​ ①自定义登录接口
​ 调用ProviderManager的方法进行认证
如果认证通过生成token,根据userId把用户信息存入redis中,返回token给前端
​ ②自定义UserDetailsService
​ 在这个实现类中去查询数据库,封装为UserDetails对象返回

校验:
​ ①定义Jwt认证过滤器
​ 获取token
​ 解析token获取其中的userid
​ 从redis中获取用户信息
​ 存入SecurityContextHolder

依赖

<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><!--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><!-- lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency><!-- security-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

yaml

spring:datasource:url: jdbc:mysql://192.168.111.101:3306/security?characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver

实现

建表、工具类、实体类

建表语句


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

JWT工具类


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;/*** JWT工具类*/
public class JwtUtil {//有效期为public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000  一个小时//设置秘钥明文public static final String JWT_KEY = "xd52s8w";public static String getUUID(){String token = UUID.randomUUID().toString().replaceAll("-", "");return token;}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @return*/public static String createJWT(String subject) {JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间return builder.compact();}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @param ttlMillis token超时时间* @return*/public static String createJWT(String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间return builder.compact();}private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;SecretKey secretKey = generalKey();long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);if(ttlMillis==null){ttlMillis=JwtUtil.JWT_TTL;}long expMillis = nowMillis + ttlMillis;Date expDate = new Date(expMillis);return Jwts.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*/public static String createJWT(String id, String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间return builder.compact();}public static void main(String[] args) throws Exception {String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg";Claims claims = parseJWT(token);System.out.println(claims);}/*** 生成加密后的秘钥 secretKey* @return*/public static SecretKey generalKey() {byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 解析** @param jwt* @return* @throws Exception*/public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}}

实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.util.Date;/*** 用户表(User)实体类*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/private Long id;/*** 用户名*/private String userName;/*** 昵称*/private String nickName;/*** 密码*/private String password;/*** 账号状态(0正常 1停用)*/private String status;/*** 邮箱*/private String email;/*** 手机号*/private String phonenumber;/*** 用户性别(0男,1女,2未知)*/private String sex;/*** 头像*/private String avatar;/*** 用户类型(0管理员,1普通用户)*/private String userType;/*** 创建人的用户id*/private Long createBy;/*** 创建时间*/private Date createTime;/*** 更新人*/private Long updateBy;/*** 更新时间*/private Date updateTime;/*** 删除标志(0代表未删除,1代表已删除)*/private Integer delFlag;
}

UserDetails: loadUserByUsername 方法返回的数据

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginUser implements UserDetails {private User user;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return null;}@Overridepublic String getPassword() {return user.getPassword ();}@Overridepublic String getUsername() {return user.getUserName ();}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
}

UserDetailsService ,通过loadUserByUsername获取用户,封装成UserDetails 对象返回

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.security.mapper.UserMapper;
import com.example.security.vo.LoginUser;
import com.example.security.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 查询用户信息LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<> ();queryWrapper.eq (User::getUserName, username);User user = userMapper.selectOne (queryWrapper);if (user == null) {// 用户不存在throw new RuntimeException ("用户不存在");}//TODO 根据用户查询权限信息 添加到LoginUser中return new LoginUser (user);}
}

加密器、AuthenticationManager

密码加密存储、登陆接口

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 密码加密存储** @return*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder ();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf ().disable ()//不通过Session获取SecurityContext.sessionManagement ().sessionCreationPolicy (SessionCreationPolicy.STATELESS).and ().authorizeRequests ()// 对于登录接口 允许匿名访问.antMatchers ("/user/login").anonymous ()// 除上面外的所有请求 全部需要鉴权认证.anyRequest ().authenticated ();}/*** 登陆接口* 通过AuthenticationManager的authenticate方法来进行用户认证* 所以需要在SecurityConfig中配置把AuthenticationManager注入容器** @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean ();}
}

登录逻辑

LoginServiceImpl 登录逻辑

import com.alibaba.fastjson.JSONObject;
import com.example.security.config.JwtUtil;
import com.example.security.vo.LoginUser;
import com.example.security.vo.ResponseResult;
import com.example.security.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Objects;@Service
public class LoginServiceImpl implements LoginServcie {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate StringRedisTemplate redisTemplate;@Overridepublic ResponseResult login(User user) {UsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken (user.getUserName (), user.getPassword ());Authentication authenticate = authenticationManager.authenticate (authenticationToken);if (Objects.isNull (authenticate)) {throw new RuntimeException ("用户名或密码错误");}// 使用userId生成tokenLoginUser loginUser = (LoginUser) authenticate.getPrincipal ();String userId = loginUser.getUser ().getId ().toString ();String token = JwtUtil.createJWT (userId);// authenticate存入redisredisTemplate.opsForValue ().set ("login:" + userId, JSONObject.toJSONString (loginUser));// 把token响应给前端HashMap<String, String> map = new HashMap<> ();map.put ("token", token);return new ResponseResult (200, "登陆成功", map);}
}

登录过滤器、配置过滤器

对需要登录的接口进行过滤,从redis中查询用户信息,未登录就 不放行

import com.alibaba.fastjson.JSONObject;
import com.example.security.vo.LoginUser;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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 java.io.IOException;
import java.util.Objects;@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Autowiredprivate StringRedisTemplate redisTemplate;/*** 对于需要登录的接口进行拦截* 看看用户信息是否存在** @param request* @param response* @param filterChain* @throws ServletException* @throws IOException*/@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {// 获取 tokenString token = request.getHeader ("token");if (!StringUtils.hasText (token)) {// 不携带token,放行filterChain.doFilter (request, response);return;}//解析tokenString userId;try {Claims claims = JwtUtil.parseJWT (token);userId = claims.getSubject ();} catch (Exception e) {e.printStackTrace ();throw new RuntimeException ("token非法");}//从redis中获取用户信息String redisKey = "login:" + userId;LoginUser loginUser = JSONObject.parseObject (redisTemplate.opsForValue ().get (redisKey), LoginUser.class);if (Objects.isNull (loginUser)) {// 没有token,就是未登录throw new RuntimeException ("用户未登录");}//存入SecurityContextHolder//TODO 获取权限信息封装到Authentication中UsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken (loginUser, null, null);SecurityContextHolder.getContext ().setAuthentication (authenticationToken);// 放行filterChain.doFilter (request, response);}
}

配置过滤器,使其生效

   @Autowiredprivate JwtAuthenticationTokenFilter filter;@Overrideprotected void configure(HttpSecurity http) throws Exception {// 把token校验过滤器 添加到过滤器链中http.addFilterBefore (filter, UsernamePasswordAuthenticationFilter.class);http//关闭csrf.csrf ().disable ()//不通过Session获取SecurityContext.sessionManagement ().sessionCreationPolicy (SessionCreationPolicy.STATELESS).and ().authorizeRequests ()// 对于登录接口 允许匿名访问.antMatchers ("/user/login").anonymous ()// 除上面外的所有请求 全部需要鉴权认证.anyRequest ().authenticated ();}

登出

将用户信息从Redis中删除
登出


public ResponseResult logout() {Authentication authentication = SecurityContextHolder.getContext ().getAuthentication ();LoginUser loginUser = (LoginUser) authentication.getPrincipal ();Long userid = loginUser.getUser ().getId ();redisTemplate.delete ("login:" + userid);return new ResponseResult (200, "退出成功");
}
http://www.hkea.cn/news/411047/

相关文章:

  • 长沙商城网站制作seo线下培训课程
  • web网站开发公司网站制作优化排名
  • 这么做3d网站企业邮箱网页版
  • 瑞安网站建设公司关键词排名网络推广
  • 南京学做网站友情链接检查工具
  • 参考文献网站开发百度重庆营销中心
  • 如何做微信ppt模板下载网站企业网页设计公司
  • 做b2b网站百度点击快速排名
  • 网站怎么做移动图片不显示不出来吗芭嘞seo
  • 旅游网站建设服务器ip域名解析
  • 企业网站建设三个原则百度指数资讯指数是指什么
  • 房地产集团网站建设方案软文文案案例
  • 阜蒙县建设学校网站是什么北京seo编辑
  • 珠海建设局网站十大经典事件营销案例分析
  • 创建网站开发公司互联网推广引流是做什么的
  • 万盛集团网站建设seo网站推广全程实例
  • 做教育的网站需要资质吗网站怎么开发
  • 微网站怎么做滚动中国万网域名注册官网
  • 个人如何免费建网站seo在线优化工具 si
  • 双线主机可以做彩票网站吗网络推广合作协议
  • 做外贸的b2b网站域名批量查询系统
  • 建设网站需要哪些职位网站建设策划书
  • 苏州网站建设哪里好网站点击排名优化
  • 网站建设收费标准策划百度推广关键词越多越好吗
  • 网站怎么做更新吗如何建立网页
  • 国外建设工程招聘信息网站tool站长工具
  • 专业做相册书的网站电商网站建设制作
  • 银川网站开发公司电话东莞网
  • 环境保护局网站管理制度建设百度指数的主要功能有
  • 安装wordpress提示500错误关键词优化的策略有哪些