springboot第25集:实体类定义规则

news2025/1/18 10:04:22

PO:持久化对象,一个PO对象对应一张表里面的一条记录。全部对应

VO:View视图对象,用来在页面中展示数据的,页面需要哪些字段属性就添加哪些,查询出来之后赋值操作比PO对象要简单。所以提高性能。

DTO:数据传递对象,如果要查询的结果集有多张表,或者从多个表获得的数据就可以封装DTO对象,把这些表的数据全部封装到一起,形成一个对象。

POJO:中间形态,可以在PO,VO,DTO之间互相转换。

POJO在保存数据,PO

POJO在表示层,VO

POJO数据传递,DTO

package com.xxx.app.controller;

import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.xxx.common.core.domain.AjaxResult;
import com.xxx.common.core.domain.entity.SysMenu;
import com.xxx.common.core.domain.entity.SysUser;
import com.xxx.common.core.domain.model.LoginBody;
import com.xxx.common.utils.SecurityUtils;
import com.xxx.framework.web.service.SysLoginService;
import com.xxx.framework.web.service.SysPermissionService;
import com.xxx.system.service.ISysMenuService;

/**
 * 登录验证
 *
 */
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
//        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
//                loginBody.getUuid());
//        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
//        AjaxResult ajax = AjaxResult.success();
//        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
//                loginBody.getUuid());
//        ajax.put(Constants.TOKEN, token);
//        return ajax;

一般流程是下面这样。

1、用户向服务器发送用户名和密码。

2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。

3、服务器向用户返回一个 session_id,写入用户的 Cookie。

4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。

5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+/=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-/替换成_ 。这就是 Base64URL 算法。

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

private String createToken(Map<String, Object> claims) {
 String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512,secret).compact();
 return token;
}
20ec7f3824cbc8950ae2181817907455.png
image.png
10092e32ba2208b76bb79187feaaca7d.png
image.png
public String createToken(LoginUser loginUser)
{
 String token = IdUtils.fastUUID();
 loginUser.setToken(token);
 setUserAgent(loginUser);
 refreshToken(loginUser);
 Map<String, Object> claims = new HashMap<>();
 claims.put(Constants.LOGIN_USER_KEY, token);
 return createToken(claims);
}
tokenService.getLoginUser(request);
Claims claims = parseToken(token);
private Claims parseToken(String token)
{
    return Jwts.parser()
            .setSigningKey(secret)
            .parseClaimsJws(token)
            .getBody();
}
private String getToken(HttpServletRequest request)
{
    String token = request.getHeader(header);
    if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
    {
        token = token.replace(Constants.TOKEN_PREFIX, "");
    }
    return token;
}
ed1e1a2e22c9fb39fc3ea65d4daafffe.png
image.png
const whiteList = [];
router.beforeEach((to, from, next) => {
 NProgress.start()
 if (getToken
})
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

添加一个配置类,配置拦截的路径

@Configuration
public class SecurityConfig extends WebSecurityConfigureAdapter {
 @Override
 protected void configure(HttpSecurity http) throws Exception {
  http.formLogin() // 表单登录
      .add()
      .authorizeRequests() // 认证配置
      .anyRequest() // 任何请求
      .authenticated(); // 需要身份验证
 }
}

编写一个简单的controller测试

@RequestMapping("hello")
@RestController
public class HelloController {
 @GetMapping("test")
 public String test() {
  return "spring security";
 }
}
e95ffa6878bf87b53b94c7789a188bb6.png
image.png

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。

(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}

Authentication authentication = SecurityContextHolder.getContext().getAuthentication()
/**
 * 获取Authentication
 */
public static Authentication getAuthentication()
{
    return SecurityContextHolder.getContext().getAuthentication();
}

Authentication: 存储了认证信息,代表当前登录用户

SeucirtyContext: 上下文对象,用来获取Authentication

SecurityContextHolder: 上下文管理对象,用来在程序任何地方获取SecurityContext

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
    return super.authenticationManagerBean();
}
@RestController
@RequestMapping("/API")
public class LoginController {
    @Autowired
    private AuthenticationManager authenticationManager;

    @PostMapping("/login")
    public String login(@RequestBody LoginParam param) {
        // 生成一个包含账号密码的认证信息
        Authentication token = new UsernamePasswordAuthenticationToken(param.getUsername(), param.getPassword());
        // AuthenticationManager校验这个认证信息,返回一个已认证的Authentication
        Authentication authentication = authenticationManager.authenticate(token);
        // 将返回的Authentication存到上下文中
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return "登录成功";
    }
}
@Autowired
private PasswordEncoder passwordEncoder;

@PostMapping("/register")
public String register(@RequestBody UserParam param) {
    UserEntity user = new UserEntity();
    // 调用加密器将前端传递过来的密码进行加密
    user.setUsername(param.getUsername()).setPassword(passwordEncoder.encode(param.getPassword()));
    // 将用户实体对象添加到数据库
    userService.save(user);
    return "注册成功";
}

认证管理器,调用,认证方法

d7b0908aa5fc9abb6969ebc49f0ad4c8.png
image.png
try
{
    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
    AuthenticationContextHolder.setContext(authenticationToken);
    // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
    authentication = authenticationManager.authenticate(authenticationToken);
}
@Service
public class UserDetailsServiceImpl implements UserDetailsService
{
}
@Resource
private AuthenticationManager authenticationManager;

调用这个认证方法

authenticate
SysUser user = userService.selectUserByUserName(username);

通过用户名查询用户

7bcde2ae9d67aeb0003dd1066b968988.png
image.png
/**
 * 强散列哈希加密实现
 */
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
{
    return new BCryptPasswordEncoder();
}

/**
 * 身份认证接口
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
2532662fe9a0ce25d67debed8ac2f139.png
image.png

loadUserByUsername

SysUser user = userService.selectUserByUserName(username);
@Override
public SysUser selectUserByUserName(String userName)
{
    return userMapper.selectUserByUserName(userName);
}
public SysUser selectUserByUserName(String userName);
9e8ae9f14050fe90442063f8065ed30a.png
image.png
public class LoginUser implements UserDetails
{
}
{
    this.userId = userId;
    this.deptId = deptId;
    this.user = user;
    this.permissions = permissions;
}
public UserDetails createLoginUser(SysUser user)
{
    return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
}
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
{
    this.userId = userId;
    this.deptId = deptId;
    this.user = user;
    this.permissions = permissions;
}

@JSONField(serialize = false)
@Override
public String getPassword()
{
    return user.getPassword();
}
197e58e3710fda4e46bf34dd6e3d8073.png
image.png
d0dd50f2cea32222b25366ff95c2fa3b.png
image.png
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
recordLoginInfo(loginUser.getUserId());
// 生成token
return tokenService.createToken(loginUser);
/**
 * 设置用户代理信息
 *
 * @param loginUser 登录信息
 */
public void setUserAgent(LoginUser loginUser)
{
    UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
    String ip = IpUtils.getIpAddr();
    loginUser.setIpaddr(ip);
    loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
    loginUser.setBrowser(userAgent.getBrowser().getName());
    loginUser.setOs(userAgent.getOperatingSystem().getName());
}
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
1e1103dfd657590c2d81e9ffcbced063.png
image.png
Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token);
return createToken(claims);
private String createToken(Map<String, Object> claims)
{
    String token = Jwts.builder()
            .setClaims(claims)
            .signWith(SignatureAlgorithm.HS512, secret).compact();
    return token;
}
token:
    # 令牌自定义标识
    header: Authorization
    # 令牌密钥
    secret: xxx
    # 令牌有效期(默认30分钟)
    expireTime: 30
return createToken(claims);

doFilterInternal

4642110aac0a0443112f88b863bfd146.png
image.png

https://zhuanlan.zhihu.com/p/342755411?utm medium=social&utm oi=1343915562263547904

01754e08a1d93ae37167b568c4836c7a.png
image.png
98582f83f9b1ba82ef8a3265ca30463c.png
image.png
5f103d91f25feb15c793e43c30b8cbb4.png
image.png
af42b00557da42066345bdb313f44a59.png
image.png
/**
 * 匿名访问不鉴权注解
 *
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous
{
}

PermitAllUrlProperties

647822e9eb259520882d91271207533a.png
image.png
aeb7c746027b65b438d1c40f6e61247b.png
image.png

https://cloud.tencentcom/document/product/400/35244

f05cf811a8de05ebfa9e330613f55470.png
image.png
d2c2c14e54d80ee4c2e080e20d653313.png
image.png
2fc876df68324a16f1b0d73286ad010a.png
image.png
0c8a98dda6e7c1251baeb34e699c593f.png
image.png
sudo /etc/init.d/bt default
a93181e0f31aa0e36df6c51685739f7c.png
image.png
cb580469075a4f4b545466545cca1d88.png
image.png
4c38896186467b8c9c54c7c87898d48b.png
image.png
db0a15e9fa0de606ddd4b8ba08442554.png
image.png

加群联系作者vx:xiaoda0423

仓库地址:https://github.com/webVueBlog/JavaGuideInterview

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/626148.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

paddle 目标检测C++部署流程

1 源码下载以及依赖库 PaddleDetectionopencv3.4.6paddle_inference10.2 2 C 编译流程 手动配置cmake的依赖库路径 报错1 报错2 报错3 编译结果 3 测试 略

梵想 S690MQ 4TB固态尝鲜,我的磁盘空间又充裕了

先上一张我的工作电脑磁盘空间图&#xff0c;系统盘装了非常多的开发环境非常吃紧&#xff0c;数据盘D盘存着大部分虚拟机估计再过没多久也要告急了&#xff0c;之前磁盘已经红过一次&#xff0c;清理了下微信聊天记录感觉还能挺几个月。 对于爱折腾系统的我 1.5T 的磁盘空间已…

数据库的增删改查(二)

1、数据库约束 关系型数据库的一个重要功能 主要作用是保证数据的完整性&#xff0c;也就是数据的正确性&#xff08;数据本身是正确的&#xff0c;关联关系也是正确的&#xff09; 人工检查数据的完整性的工作量非常的大&#xff0c;在数据表定义一些约束&#xff0c;那数据…

从“制造”到“智造”!宏工科技发布“宏梦智能制造云”新产品

产业周期性变化正在给锂电产业带来深刻变革。6月7日&#xff0c;宏工科技在2023高工锂电材料大会上发表演讲表示&#xff0c;宏工科技推出了“宏梦智能制造云”&#xff0c;以整线一体化智造思路&#xff0c;赋能电池材料生产智造转型。 全球电动化与储能市场双轮驱动&#xff…

GPS跟踪系统Traccar

什么是 Traccar &#xff1f; Traccar是一个开源的 GPS 跟踪系统。支持 200多种GPS 协议和 2000 多种型号的 GPS 跟踪设备。当然也包括像 iOS/Android 这样的手机设备&#xff0c;手机设备只需要安装Traccar的客户端即可使用。 前文介绍的 Hauk 只支持 Android 客户端&#xff…

数据分析第13课Matplotlib可视化

官网:https://matplotlib.org/users/installing.html 04-1Matplotlib介绍与安装 Matplotlib介绍 什么是Matplotlib Matplotlib是一个Python的基础绘图库,它可与 NumPy(科学计算的) 一起使用,代替Matlab(计算很好)使用。 为什么要学习Matplotlib(灵活度高) 将数据…

AutoHotKey文件与路径交互操作

文章目录 路径操作文件选择文件读写文件属性 AHK作为一种脚本语言&#xff0c;其功能特点是对操作系统功能的整合与简化&#xff0c;从而缩减操作流程&#xff0c;从而起到提高效率的目的。鼠标、键盘的映射&#xff0c;相当于是对外设操作的简化&#xff0c;而除了外部交互之外…

docker harbor私有仓库部署

docker harbor私有仓库部署 docker system prune -a 删除停掉的服务&#xff0c;自定义网络等。 docker 私有仓库 docker配置文件 vim /etc/docker.daemon.josn { “insecury-registries”: ["192.168.232.10:5000]&#xff0c;#指定私有仓库 } docker pull/push 19…

chatgpt赋能python:Python中引入其他包的指南

Python中引入其他包的指南 Python是一种流行的编程语言&#xff0c;拥有丰富的开源软件包和库。许多Python程序将使用其他包来增强其功能。在本文中&#xff0c;我们将探讨如何在Python项目中使用和引入其他包。 什么是Python包和库&#xff1f; Python包是一组可重复使用的…

冈萨雷斯DIP第7章知识点

文章目录 7.3 相关7.5 基图像7.6 傅里叶相关变换7.6.1 离散哈特利变换7.6.3 离散正弦变换 DIP的其他章节都好复习&#xff0c;唯独就这个第7章小波变换。复习起来十分头大&#xff0c;所以我开始写他的课后题&#xff0c;雾。 7.3 相关 已知两个连续函数 f ( x ) f(x) f(x) …

单链表【数据结构、数组模拟】

不采用动态链表 一般情况下&#xff0c;都是直接使用下面的代码进行模拟的 struct Node{int val;Node *next; }然后当我们需要进行创建一个新的节点时&#xff0c;都需要使用new Node()&#xff0c;非常慢&#xff01;&#xff01;&#xff01; 数据规模一般都是10w~100w的数…

Android性能分析工具:Perfetto介绍及用法

本文字数&#xff1a;8409字 预计阅读时间&#xff1a;22分钟 概念 什么是Perfetto?Perfetto是Android 10中引入的全新平台级跟踪工具。这是适用于Android、Linux和Chrome的更加通用和复杂的开源跟踪项目。与Systrace不同&#xff0c;它提供数据源超集&#xff0c;可让您以pro…

【6.09 代随_52day】 最长递增子序列、最长连续递增序列、最长重复子数组

最长递增子序列、最长连续递增序列、最长重复子数组 最长递增子序列1.方法图解步骤递归代码 最长连续递增序列1.动态规划的方法图解步骤代码 最长重复子数组图解步骤代码 最长递增子序列 力扣连接&#xff1a;300. 最长递增子序列&#xff08;中等&#xff09; 1.方法 dp[i]…

开源 Golang 微服务入门三:ORM 框架 GORM

前言 前两篇笔记分别介绍了 Golang 微服务 HTTP 框架 Hertz 和 Golang 微服务 RPC 框架 Kitex&#xff0c;本文将要介绍面向ORM(持久层)框架 GORM。 官方文档 GORM 是面向 Golang 语言的一种 ORM(持久层)框架&#xff0c;支持多种数据库的接入&#xff0c;例如 MySQL&#x…

【TCP/IP】多进程服务器的实现(进阶) - 僵尸进程及wait、waitpid函数

目录 僵尸(Zombie)进程 僵尸进程的产生机制 僵尸进程的危害 僵尸进程的销毁 wait函数 waitpid函数 进程管理在网络编程中十分重要&#xff0c;如果未处理好&#xff0c;将会导致出现“僵尸进程”&#xff0c;进而影响服务器端对进程的管控。 僵尸(Zombie)进程 第一次听到…

继万物分割SAM之后,万物识别模型RAM来了!

Recognize Anything: A Strong Image Tagging Model 提出“识别万物模型”&#xff08;Recognize Anything Model&#xff0c;RAM&#xff09;&#xff0c;用于图像打标签。RAM 可以高精度地识别任何常见类别。RAM 引入了图像打标签的一个新范式&#xff0c;利用大规模的图像-文…

如何在RPC和RESTful之间做选择?

不同软件系统之间的通信可以通过RPC&#xff08;远程过程调用&#xff09;或RESTful&#xff08;表现层状态转移&#xff09;协议来建立&#xff0c;这些协议允许多个系统在分布式计算中协同工作。 这两种协议在设计哲学上有所区别。RPC使得可以像调用本地过程一样调用服务器上…

AI时代已经到来,不想被抛弃,特别是传统产业的你,怎么办?

由于ChatGTP的惊人表现&#xff0c;本来已经趋于平淡的AI&#xff0c;又火爆起来。毫无疑问&#xff0c;人类已经进入了AI时代&#xff0c;AI将渗入到各行各业&#xff0c;渗入到生活与工作的每个方面。这是一场新的工业革命&#xff0c;很多工作都将消失&#xff0c;但也会产生…

【Python】Python进阶系列教程-- Python3 MySQL - mysql-connector 驱动(三)

文章目录 前言创建数据库连接创建数据库创建数据表主键设置 插入数据批量插入查询数据where 条件语句排序Limit删除记录更新表数据删除表 前言 往期回顾&#xff1a; Python进阶系列教程-- Python3 正则表达式&#xff08;一&#xff09;Python进阶系列教程-- Python3 CGI编程…

记录--7 个沙雕又带有陷阱的 JS 面试题

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 为了保证的可读性&#xff0c;本文采用意译而非直译。 在 JS 面试中&#xff0c;经常会看到一些简单而又沙雕的题目&#xff0c;这些题目包含一些陷阱&#xff0c;但这些在我们规范的编码下或者业务中…