shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。

简介: 这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。

前言

一、逻辑

1. 登录逻辑

shiro 做安全权限控制。那么shiro的过滤器和数据源的处理主要是针对token的认证和授权。
而用户的密码验证则还是在service层中进行处理。

  1. 首先将用户登录的接口 /user/login 在shiro过滤器中放开,不在拦截,设置为 anon
  2. 发送post请求携带用户名和密码,进行登录。走这个请求时,在上一步已经被设置了白名单。走控制器,业务层service,在这里进行判断,用户名密码判断无误后,设置token和id,然后返回到前端。
  3. 总结一下:用户的密码登录和shiro是无关的,正常的判断即可。注意的是需要返回的数据,这里仅有id和token。token也是UUID生成的,并存在redis中。
  4. 访问其他接口时,拿着token放在请求头中,然后发请求,没有被shiro设置在白名单里的请求会被shiro拦截,拦截流程如下:
    ShiroAccessControlFilter类:isAccessAllowed():onAccessDenied(),用到了ShiroUsernamePasswordToken
    ->ShiroRealm类:doGetAuthenticationInfo方法
    ->ShiroHashedCredentialsMatcher类:doCredentialsMatch()
  5. 根据博客三,这里重写的doCredentialsMatch()方法就是 shiro的过滤器的最后一步,也是至关重要的一步。
    6. 接下来就可以去控制的接口了,如果遇到@RequiresPermissions() 注解,再去ShiroRealm类中doGetAuthorizationInfo()授权方法去授予权限即可,再去接口即可。

2. 项目目录结构

在这里插入图片描述

3. 开发逻辑

a. redis 开发工具类

redis的配置类和工具类,我就不再贴出,本博客主要写shiro的代码,代码可去GitHub上拉取下来观看

  1. config包下的RedisConfig配置类
  2. serializer包下的MyStringRedisSerializer序列化类
  3. utils包下的RedisUtil类

代码不再贴了,都在GitHub上

b. 密码加密工具类

  1. utils 包下的 PasswordUtils 工具类。
  2. PasswordEncoder密码编码类。

代码不再贴了,都在GitHub上

c. swagger配置

  1. config包下的 SwaggerConfig配置类
  2. 配置类上的启动注解 @EnableSwagger2

代码不再贴了,都在GitHub上

d. shiro开发 流程

  1. 先开发 ShiroConfig,设置自定义过滤器 ShiroAccessControlFilter,并设置过滤器的白名单
    对登录的请求设置为 anon。
  2. 开发 ShiroAccessControlFilter拦截器,这里是对 token 的简单过滤验证,并进行主体提交,提交到自定义数据域 realm。
    开发拦截器中,还要开发ShiroUsernamePasswordToken,自己实现shiro认证机制,就要重写类 UsernamePasswordToken
  3. 开发自定义realm:ShiroRealm类。数据域部分,进行授权和认证。
    认证:对token进行过滤,用户名密码登录部分还是在业务层处理
    授权:从数据库中获取,设计到表 role、permission、user_role、role_permission 四个表
  4. 开发 token 的最后过滤处理 ShiroHashedCredentialsMatcher,继承 HashedCredentialsMatcher类实现方法doCredentialsMatch()

以上四步其实就是 shiro 开发的全部,基本上都是配置式的代码。

二、shiro代码开发

1. shiroConfig.java

package com.feng.config;

import com.feng.shiro.ShiroAccessControlFilter;
import com.feng.shiro.ShiroHashedCredentialsMatcher;
import com.feng.shiro.ShiroRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    /**
     * token 的过滤
     * 自定义token 校验
     * 学习说明:其实 下面的 ShiroHashedCredentialsMatcher(自定义的) 也继承了 HashedCredentialsMatcher。
     * 需要在 CustomRealm bean 中进行设置
     * @return
     */
    @Bean(name = "shiroHashedCredentialsMatcher")
    public ShiroHashedCredentialsMatcher shiroHashedCredentialsMatcher() {
        return new ShiroHashedCredentialsMatcher();
    }

    /**
     * 登录的 认证域
     *
     * @param hashedCredentialsMatcher
     * @return
     */
    @Bean(name = "shiroRealm")
    public ShiroRealm getShiroRealm(@Qualifier("shiroHashedCredentialsMatcher") HashedCredentialsMatcher hashedCredentialsMatcher) {
        ShiroRealm shiroRealm = new ShiroRealm();
        // 自定义 处理 token 过滤
        shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return shiroRealm;
    }

    /**
     * shiro 的安全管理器
     *
     * @param shiroRealm
     * @return
     */
    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("shiroRealm") ShiroRealm shiroRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm);
        return securityManager;
    }
    /**
     * shiro 的过滤器
     * 需要了解 shiro 的权限关键字含义:
     *  anon,表示不拦截的路径
     *  authc,表示拦截的路径
     *
     *  匹配时,首先匹配 anon 的,然后最后匹配 authc
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /*
         * 自定义过滤器
         * */
        //自定义拦截器限制并发人数,参考博客:
        LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();
        //用来校验token
        filtersMap.put("token", new ShiroAccessControlFilter());
        shiroFilterFactoryBean.setFilters(filtersMap);
        /*
         * 以下为权限控制
         * */
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/user/login", "anon");
//        filterChainDefinitionMap.put("/user/test", "anon");

        // 拦截所有
        filterChainDefinitionMap.put("/**", "token,authc");

        // 没有登录的用户请求需要登录的页面时自动跳转到登录页面。 配置 shiro 默认登录界面地址,
        shiroFilterFactoryBean.setLoginUrl("/api/user/login");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 下面两个配置类 AuthorizationAttributeSourceAdvisor 和 DefaultAdvisorAutoProxyCreator,开启 shiro aop 注解 支持.
     * 使用代理方式;所以需要开启代码支持;
     * <p>
     * 如果不加 使用 @RequirePermissions 无效
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
}

2. ShiroAccessControlFilter

package com.feng.shiro;

import com.alibaba.fastjson.JSON;
import com.feng.constant.Constant;
import com.feng.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: CustomAccessControlerFilter
 * @Description: 自定义的 token 过滤器。
 * @createTime:
 * @Author: 冯凡利
 * @UpdateUser: 冯凡利
 * @Version: 0.0.1
 */

/**
 * 这里的异常,全局异常无法处理,比较高级没有到达 方法,所以需要自己处理  try-catch
 */
@Slf4j
public class ShiroAccessControlFilter extends AccessControlFilter {
    /**
     * 是否 允许 访问下一层
     * true: 允许,交下一个Filter 处理
     * false: 交给自己处理,往下执行 onAccessDenied 方法
     * @param servletRequest
     * @param servletResponse
     * @param o
     * @return
     * @throws Exception
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
        return false;
    }

    /**
     * 表示访问拒绝时是否自己处理,
     * 如果返回 true 表示自己不处理且 继续拦截器执行,往下执行
     * 返回 false 表示自己已经处理了(比如重定向到另一个界面)处理完毕。
     *
     * @param servletRequest
     * @param servletResponse
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        try {
            log.info("接口请求方式{}",request.getMethod());
            log.info("接口请求地址",request.getRequestURI());
            String token=request.getHeader(Constant.TOKEN_SESSION_ID);
            if(StringUtils.isEmpty(token)){
                throw new BusinessException(4010001,"用户凭证已失效请重新登录认证");
            }
            ShiroUsernamePasswordToken customUsernamePasswordToken=new ShiroUsernamePasswordToken(token);
            getSubject(servletRequest,servletResponse).login(customUsernamePasswordToken);
        } catch (BusinessException e) {
            customResponse(e.getMessageCode(),e.getMessage(),servletResponse);
            return false;
        } catch (AuthenticationException e) {
            if(e.getCause() instanceof BusinessException){
                BusinessException businessException= (BusinessException) e.getCause();
                customResponse(businessException.getMessageCode(),businessException.getMessage(),servletResponse);
            }else {
                customResponse(4000001,"用户认证失败",servletResponse);
            }
            return false;
        }catch (Exception e){
            customResponse(5000001,"系统异常",servletResponse);
            return false;
        }
        return true;
    }

    /**
     * 异常处理
     * 因为这里的位置是高于业务层的,所以这里的异常只能通过流的形式输出到前端。
     * @param code
     * @param msg
     * @param response
     */
    private void customResponse(int code, String msg, ServletResponse response) {
        // 自定义异常的类,用户返回给客户端相应的JSON格式的信息
        try {
            Map<String, Object> result = new HashMap<>();
            result.put("code", code);
            result.put("msg", msg);
            response.setContentType("application/json; charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            String userJson = JSON.toJSONString(result);
            // 写入到 流中,返回到客户端
            OutputStream out = response.getOutputStream();
            out.write(userJson.getBytes(StandardCharsets.UTF_8));
            out.flush();
        } catch (IOException e) {
            log.error("eror={}", e.getLocalizedMessage());
        }
    }
}

3. ShiroUsernamePasswordToken

package com.feng.shiro;

import org.apache.shiro.authc.UsernamePasswordToken;

public class ShiroUsernamePasswordToken extends UsernamePasswordToken {

    private String token;

    public ShiroUsernamePasswordToken(String token) {
        this.token = token;
    }

    @Override
    public Object getPrincipal() {
        return token;
    }

    @Override
    public Object getCredentials() {
        return token;
    }
}

4. ShiroRealm

package com.feng.shiro;

import com.feng.bean.SysUser;
import com.feng.service.PermissionService;
import com.feng.service.RoleService;
import com.feng.service.UserService;
import com.feng.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Slf4j
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Resource
    private RoleService roleService;

    @Resource
    private PermissionService permissionService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 设置支持令牌校验
     *
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof ShiroUsernamePasswordToken;
    }

    /**
     * 授权
     * 主要业务:
     * 系统业务出现要验证用户的角色权限的时候,就会调用这个方法
     * 来获取该用户所拥有的角色/权限
     * 这个用户授权的方法我们可以缓存起来不用每次都调用这个方法。
     * 后续的课程我们会结合 redis 实现它
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("ShiroRealm.doGetAuthorizationInfo()");
        String token= (String) principalCollection.getPrimaryPrincipal();
        String userId= (String) redisUtil.get(token);
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();

        //返回该用户的 角色信息 给授权器
        List<String> roleNames = roleService.getRoleNamesByUserId(userId);
        if (null != roleNames && !roleNames.isEmpty()) {
            info.addRoles(roleNames);
        }
        //返回该用户的 权限信息 给授权器
        Set<String> permissionPerms = permissionService.getPermissionPermsByUserId(userId);
        if (permissionPerms != null) {
            info.addStringPermissions(permissionPerms);
        }
        return info;
    }

    /**
     * 认证
     * 主要业务:
     * 当业务代码调用 subject.login(customPasswordToken); 方法后
     * 就会自动调用这个方法 验证用户名/密码
     * 这里我们改造成 验证 token 是否有效 已经自定义了 shiro 验证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("ShiroRealm.doGetAuthenticationInfo()");
        ShiroUsernamePasswordToken token = (ShiroUsernamePasswordToken) authenticationToken;
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo((String)token.getPrincipal(), (String)token.getCredentials(), ShiroRealm.class.getName());
        return info;
    }

    private List<String> getRoleByUserId(String userId){
        List<String> roles=new ArrayList<>();
        if(userId.equals("8a938151-53e6-4182-925a-684f3be840e8")){
            roles.add("admin");
        }
        roles.add("test");
        return roles;
    }

    private List<String> getPermissionsByUserId(String userId){
        List<String> permissions=new ArrayList<>();
        if(userId.equals("8a938151-53e6-4182-925a-684f3be840e8")){
            permissions.add("*");
        }
        permissions.add("sys:user:detail");
        permissions.add("sys:user:edit");
        return permissions;
    }
}

5. ShiroHashedCredentialsMatcher

public class ShiroHashedCredentialsMatcher extends HashedCredentialsMatcher {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        ShiroUsernamePasswordToken shiroUsernamePasswordToken= (ShiroUsernamePasswordToken) token;
        String accessToken = (String) shiroUsernamePasswordToken.getPrincipal();
        if(!redisUtil.hasKey(accessToken)){
            throw new BusinessException(4001002,"授权信息信息无效请重新登录");
        }
        return true;
    }
}

三、业务逻辑控制层代码

package com.feng.controller;

import com.feng.bean.SysUser;
import com.feng.service.UserService;
import com.feng.vo.LoginReqVO;
import com.feng.vo.LoginRespVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/user")
@Api(tags = "用户模块",description = "用户模块相关接口")
public class LoginController {

    @Autowired
    private UserService userService;

    @GetMapping("/page")
    public String index() {
        return "login";
    }

    /**
     * 前端用表单发请求如果使用 form-data、x-www-form-urlencoded 获取 ,则不可用 @RequestBody接受(因为他接受的为json)
     * @param loginReqVO
     * @return
     */
    @ApiOperation(value = "用户登录接口")
    @PostMapping(value = "/login")
    @ResponseBody
    public Map<String, Object> loginUser(@RequestBody LoginReqVO loginReqVO) {
        LoginRespVO info = userService.login(loginReqVO);
        Map<String, Object> result = new HashMap<>();
        result.put("code", 0);
        result.put("data", info);
        return result;
    }

    @ApiOperation(value = "获取用户详情接口")
    @GetMapping("/getuser/{id}")
    @RequiresPermissions("sys:user:detail")
    public Map<String, Object> getUserAllInfo(@PathVariable("id") String id){
        Map<String, Object> result = new HashMap<>();
        SysUser detail = userService.detail(id);
        result.put("code", 0);
        result.put("data", detail);
        return result;
    }

    @GetMapping("/test")
    public Map<String, Object> test(){
        Map<String, Object> result = new HashMap<>();
        result.put("code", 0);
        result.put("data", "sucess");
        return result;
    }
}

五、postman测试和debug分析

1. 登录

登录的URL 在 ShiroConfig.shiroFilterFactoryBean() 方法中已经被设置成了白名单,在shiro的各处打了断电,也不会进入。直接进入到控制器层返回用户id和token。

http://localhost:8082/user/login
{
    "username": "feng",
    "password": "666666"
}

在这里插入图片描述

2. 获取用户信息

此URL 已经被设置走自定义的 ShiroAccessControlFilter 过滤器。
所以debug发请求分析如下:

  1. 先进入 ShiroAccessControlFilter.isAccessAllowed() 方法
  2. 进入到源码 AccessControlFilter.onPreHandle() 方法,这个方法会调用上面的方法和下面的方法
  3. 在进入到 ShiroAccessControlFilter.onAccessDenied() 方法,在这里获取token,并简单验证token是否存在,然后进行 shiro的主体登录。(一会儿,还会返回来)
  4. 主体登录后,debug 跳转到 ShiroRealm.doGetAuthenticationInfo() 进行认证。
  5. 然后流转到 自定义的核心验证类和方法ShiroHashedCredentialsMatcher.doCredentialsMatch() 方法 。
  6. 然后返回到第三步 的 ShiroAccessControlFilter.onAccessDenied() 方法 的最后一行返回值,返回值为 true。
  7. 然后流转到 ShiroRealm.doGetAuthorizationInfo() 进行授权。这里进入到授权方法是因为在控制器方法上有注解:@RequiresPermissions("sys:user:detail")
http://localhost:8082/user/getuser/8a938151-53e6-4182-925a-684f3be840e8

在这里插入图片描述

六、注意的点

1. 数据库表的设计

用户登录只涉及到 user 表
shiro的权限授权部分涉及到 role、permission、user_role、role_permission 表。

2. shiro的认证授权流程

一定要多分析下shiro的认证流程,代码执行流程的走向。

相关文章
|
4月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
621 5
|
11月前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
1059 79
|
12月前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
1713 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
12月前
|
JavaScript 前端开发 Java
Jeesite5:Star24k,Spring Boot 3.3+Vue3实战开源项目,架构深度拆解!让企业级项目开发效率提升300%的秘密武器
Jeesite5 是一个基于 Spring Boot 3.3 和 Vue3 的企业级快速开发平台,集成了众多优秀开源项目,如 MyBatis Plus、Bootstrap、JQuery 等。它提供了模块化设计、权限管理、多数据库支持、代码生成器和国际化等功能,极大地提高了企业级项目的开发效率。Jeesite5 广泛应用于企业管理系统、电商平台、客户关系管理和知识管理等领域。通过其强大的功能和灵活性,Jeesite5 成为了企业级开发的首选框架之一。访问 [Gitee 页面](https://gitee.com/thinkgem/jeesite5) 获取更多信息。
674 0
Jeesite5:Star24k,Spring Boot 3.3+Vue3实战开源项目,架构深度拆解!让企业级项目开发效率提升300%的秘密武器
|
NoSQL Linux Redis
Docker学习二(Centos):Docker安装并运行redis(成功运行)
这篇文章介绍了在CentOS系统上使用Docker安装并运行Redis数据库的详细步骤,包括拉取Redis镜像、创建挂载目录、下载配置文件、修改配置以及使用Docker命令运行Redis容器,并检查运行状态和使用Navicat连接Redis。
1520 3
|
NoSQL API Redis
如何使用 C++ 开发 Redis 模块
如何使用 C++ 开发 Redis 模块
|
12月前
|
云安全 安全 数据建模
《数字证书:互联网世界的"身份证"与"防盗门"》 ——揭秘网络安全背后的加密江湖
在2023年某深夜,上海陆家嘴金融公司机房遭遇黑客攻击,神秘青铜大门与九大掌门封印的玉牌突现,阻止了入侵。此门象征数字证书,保障网络安全。数字证书如验钞机识别假币,保护用户数据。它通过SSL/TLS加密、CA认证和非对称加密,构建安全通信。证书分为DV、OV、EV三类,分别适合不同场景。忽视证书安全可能导致巨额损失。阿里云提供一站式证书服务,助力企业部署SSL证书,迎接未来量子计算和物联网挑战。
|
安全 算法 网络协议
【网络原理】——图解HTTPS如何加密(通俗简单易懂)
HTTPS加密过程,明文,密文,密钥,对称加密,非对称加密,公钥和私钥,证书加密
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将从网络安全漏洞、加密技术和安全意识三个方面进行探讨,旨在提高读者对网络安全的认识和防范能力。通过分析常见的网络安全漏洞,介绍加密技术的基本原理和应用,以及强调安全意识的重要性,帮助读者更好地保护自己的网络信息安全。
257 10
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。