前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot第25集:实体类定义规则

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

作者头像
达达前端
发布2023-10-08 18:34:16
2450
发布2023-10-08 18:34:16
举报
文章被收录于专栏:达达前端

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

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

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

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

POJO在保存数据,PO

POJO在表示层,VO

POJO数据传递,DTO

代码语言:javascript
复制
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));
    }
}
代码语言:javascript
复制
//        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字段里面。

代码语言:javascript
复制
private String createToken(Map<String, Object> claims) {
 String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512,secret).compact();
 return token;
}
20ec7f3824cbc8950ae2181817907455.png
20ec7f3824cbc8950ae2181817907455.png

image.png

10092e32ba2208b76bb79187feaaca7d.png
10092e32ba2208b76bb79187feaaca7d.png

image.png

代码语言:javascript
复制
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);
}
代码语言:javascript
复制
tokenService.getLoginUser(request);
代码语言:javascript
复制
Claims claims = parseToken(token);
代码语言:javascript
复制
private Claims parseToken(String token)
{
    return Jwts.parser()
            .setSigningKey(secret)
            .parseClaimsJws(token)
            .getBody();
}
代码语言:javascript
复制
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
ed1e1a2e22c9fb39fc3ea65d4daafffe.png

image.png

代码语言:javascript
复制
const whiteList = [];
router.beforeEach((to, from, next) => {
 NProgress.start()
 if (getToken
})
代码语言:javascript
复制
<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>

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

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

编写一个简单的controller测试

代码语言:javascript
复制
@RequestMapping("hello")
@RestController
public class HelloController {
 @GetMapping("test")
 public String test() {
  return "spring security";
 }
}
e95ffa6878bf87b53b94c7789a188bb6.png
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 协议传输。

代码语言:javascript
复制
@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()
代码语言:javascript
复制
/**
 * 获取Authentication
 */
public static Authentication getAuthentication()
{
    return SecurityContextHolder.getContext().getAuthentication();
}

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

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

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

代码语言:javascript
复制
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
    return super.authenticationManagerBean();
}
代码语言:javascript
复制
@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 "登录成功";
    }
}
代码语言:javascript
复制
@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
d7b0908aa5fc9abb6969ebc49f0ad4c8.png

image.png

代码语言:javascript
复制
try
{
    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
    AuthenticationContextHolder.setContext(authenticationToken);
    // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
    authentication = authenticationManager.authenticate(authenticationToken);
}
代码语言:javascript
复制
@Service
public class UserDetailsServiceImpl implements UserDetailsService
{
}
代码语言:javascript
复制
@Resource
private AuthenticationManager authenticationManager;

调用这个认证方法

代码语言:javascript
复制
authenticate
代码语言:javascript
复制
SysUser user = userService.selectUserByUserName(username);

通过用户名查询用户

7bcde2ae9d67aeb0003dd1066b968988.png
7bcde2ae9d67aeb0003dd1066b968988.png

image.png

代码语言:javascript
复制
/**
 * 强散列哈希加密实现
 */
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
{
    return new BCryptPasswordEncoder();
}

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

image.png

loadUserByUsername

代码语言:javascript
复制
SysUser user = userService.selectUserByUserName(username);
代码语言:javascript
复制
@Override
public SysUser selectUserByUserName(String userName)
{
    return userMapper.selectUserByUserName(userName);
}
代码语言:javascript
复制
public SysUser selectUserByUserName(String userName);
9e8ae9f14050fe90442063f8065ed30a.png
9e8ae9f14050fe90442063f8065ed30a.png

image.png

代码语言:javascript
复制
public class LoginUser implements UserDetails
{
}
代码语言:javascript
复制
{
    this.userId = userId;
    this.deptId = deptId;
    this.user = user;
    this.permissions = permissions;
}
代码语言:javascript
复制
public UserDetails createLoginUser(SysUser user)
{
    return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
}
代码语言:javascript
复制
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
197e58e3710fda4e46bf34dd6e3d8073.png

image.png

d0dd50f2cea32222b25366ff95c2fa3b.png
d0dd50f2cea32222b25366ff95c2fa3b.png

image.png

代码语言:javascript
复制
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
代码语言:javascript
复制
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
recordLoginInfo(loginUser.getUserId());
// 生成token
return tokenService.createToken(loginUser);
代码语言:javascript
复制
/**
 * 设置用户代理信息
 *
 * @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());
}
代码语言:javascript
复制
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
1e1103dfd657590c2d81e9ffcbced063.png
1e1103dfd657590c2d81e9ffcbced063.png

image.png

代码语言:javascript
复制
Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token);
return createToken(claims);
代码语言:javascript
复制
private String createToken(Map<String, Object> claims)
{
    String token = Jwts.builder()
            .setClaims(claims)
            .signWith(SignatureAlgorithm.HS512, secret).compact();
    return token;
}
代码语言:javascript
复制
token:
    # 令牌自定义标识
    header: Authorization
    # 令牌密钥
    secret: xxx
    # 令牌有效期(默认30分钟)
    expireTime: 30
代码语言:javascript
复制
return createToken(claims);

doFilterInternal

4642110aac0a0443112f88b863bfd146.png
4642110aac0a0443112f88b863bfd146.png

image.png

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

01754e08a1d93ae37167b568c4836c7a.png
01754e08a1d93ae37167b568c4836c7a.png

image.png

98582f83f9b1ba82ef8a3265ca30463c.png
98582f83f9b1ba82ef8a3265ca30463c.png

image.png

5f103d91f25feb15c793e43c30b8cbb4.png
5f103d91f25feb15c793e43c30b8cbb4.png

image.png

af42b00557da42066345bdb313f44a59.png
af42b00557da42066345bdb313f44a59.png

image.png

代码语言:javascript
复制
/**
 * 匿名访问不鉴权注解
 *
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous
{
}

PermitAllUrlProperties

647822e9eb259520882d91271207533a.png
647822e9eb259520882d91271207533a.png

image.png

aeb7c746027b65b438d1c40f6e61247b.png
aeb7c746027b65b438d1c40f6e61247b.png

image.png

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

f05cf811a8de05ebfa9e330613f55470.png
f05cf811a8de05ebfa9e330613f55470.png

image.png

d2c2c14e54d80ee4c2e080e20d653313.png
d2c2c14e54d80ee4c2e080e20d653313.png

image.png

2fc876df68324a16f1b0d73286ad010a.png
2fc876df68324a16f1b0d73286ad010a.png

image.png

0c8a98dda6e7c1251baeb34e699c593f.png
0c8a98dda6e7c1251baeb34e699c593f.png

image.png

代码语言:javascript
复制
sudo /etc/init.d/bt default
a93181e0f31aa0e36df6c51685739f7c.png
a93181e0f31aa0e36df6c51685739f7c.png

image.png

cb580469075a4f4b545466545cca1d88.png
cb580469075a4f4b545466545cca1d88.png

image.png

4c38896186467b8c9c54c7c87898d48b.png
4c38896186467b8c9c54c7c87898d48b.png

image.png

db0a15e9fa0de606ddd4b8ba08442554.png
db0a15e9fa0de606ddd4b8ba08442554.png

image.png

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档