这里写目录标题
day(3-22日)shiro框架的应用
1、认证
知识点补充
认证方式:用户+密码
-
1.2、shiro的步骤以及关键
- 1、添加依赖
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.8.0</version> </dependency>-
2、控制层
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);会将这个对象传递给自定义并且继承AuthenticatingRealm类
@PostMapping("/login") public String login(String username, String password) { UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password); try { SecurityUtils.getSubject().login(usernamePasswordToken);//将corller层的数据传到token } catch (UnknownAccountException uae) { } catch (LockedAccountException lae) { } return ""; } -
3、配置类
- 配置路径拦截器
- 自定义继承类继承不同的类
认证 、密码加密 AuthenticatingRealm 抽象* 授权
-
权限 AuthorizingRealm
-
配置拦截器
-
一开始所有的默认拦截所有的请求
-
anon 不需要认证的 authc 其他所有都需要认证
@Bean("filterChainDefinition") public ShiroFilterChainDefinition filterChainDefinition() { DefaultShiroFilterChainDefinition shiroFilterChainDefinition = new DefaultShiroFilterChainDefinition(); /** * 不需要认证的 */ shiroFilterChainDefinition.addPathDefinition("/login", "anon"); shiroFilterChainDefinition.addPathDefinition("/register", "anon"); // shiroFilterChainDefinition.addPathDefinition("/druid/**", "anon"); // 其他所有都需要认证 shiroFilterChainDefinition.addPathDefinition("/**", "authc"); return shiroFilterChainDefinition; } -
1.3自定义配置类(继承AuthenticatingRealm抽象类)
认证 、加密 AuthenticatingRealm 抽象* 授权
权限 AuthorizingRealm
-
a、doGetAuthenticationInfo来进行权限的验证并从前端获取数据(前端获取数据)
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { /** * 1 获取客服端传递过来的用户名 */ String username = (String) authenticationToken.getPrincipal(); Member member = memberMapper.findByUsername(username); if (member == null) { throw new UnknownAccountException(); } if (member.getStatus() == 0) { throw new LockedAccountException(); } /** * * * Object principal, 从数据库中获取的用户对象 * Object hashedCredentials, 用户的密码 * ByteSource credentialsSalt, 加密盐 因为加密算法是公开 * String realmName 从前端传递登录用户名 */ SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(member,member.getPassword(),null,username); return simpleAuthenticationInfo; } -
b
-
报错解决
2、加密
-
1、配置类配置
-
注册
/** * 基于数据数据用户表验证 */ @Bean public UserRealm realm(HashedCredentialsMatcher hashedCredentialsMatcher) { UserRealm userRealm = new UserRealm(); // 注册到realm中 userRealm.setCredentialsMatcher(hashedCredentialsMatcher); return userRealm; } -
配置加密算法
注册 /** * 配置密码加密算法 * @return */ @Bean @Primary public HashedCredentialsMatcher hashedCredentialsMatcher(){ //以md5进行加密 HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(Md5Hash.ALGORITHM_NAME); //散列的次数,默认1次, 设置两次相当于 md5(md5("")); hashedCredentialsMatcher.setHashIterations(ShiroUtils.HASH_ITERATIONS); return hashedCredentialsMatcher; } }3、权限认证
-
-
1、概论
-
1.1、权限的分类
- 数据权限 url
- 资源权限 文件
- 菜单权限
- 元素权限
-
1.2、权限mysql
CREATE TABLE member_role_relation ( id int AUTO_INCREMENT PRIMARY KEY, role_id int NOT NULL COMMENT '角色主键', member_id bigint NOT NULL COMMENT '会员ID' ); CREATE TABLE sys_role ( role_id int AUTO_INCREMENT PRIMARY KEY COMMENT '主键', name varchar(32) UNIQUE NOT NULL COMMENT '角色名', decl varchar(255) COMMENT '角色说明', status int DEFAULT 1 COMMENT '是否启用 1 启用 0 禁用' ) COMMENT '角色表'; CREATE TABLE sys_permission ( per_id int AUTO_INCREMENT PRIMARY KEY COMMENT '主键', name varchar(128) UNIQUE NOT NULL COMMENT '权限名', decl varchar(255) COMMENT '权限说明', status int DEFAULT 1 COMMENT '是否启用 1 启用 0 禁用' ) COMMENT '权限表'; CREATE TABLE role_permission_relation ( id int AUTO_INCREMENT PRIMARY KEY COMMENT '主键', role_id int NOT NULL COMMENT '角色主键', per_id int NOT NULL COMMENT '权限主键' ) COMMENT '角色与权限表';
-
-
2、自定义类并继承AuthorizingRealm
/** * 1 获取客服端传递过来的用户名 */ String username = (String) authenticationToken.getPrincipal(); Member member = memberMapper.findByUsername(username); if (member == null) { throw new UnknownAccountException(); } if (member.getStatus() == 0) { throw new LockedAccountException(); } /** * * * Object principal, 从数据库中获取的用户对象 * Object hashedCredentials, 用户的密码 * ByteSource credentialsSalt, 加密盐 因为加密算法是公开 * String realmName 从前端传递登录用户名 */ SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(member,member.getPassword(),null,username); return simpleAuthenticationInfo; } @Resource RolePermissionMapper rolePermissionMapper; //这句是授权的观念建 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { // 1 获取登录用户信息,该对象包含当前授权用户的名 Member member = (Member) principalCollection.getPrimaryPrincipal(); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); // 2 通过用户ID获取所有的角色权限信息 Long memberId = member.getMemberId(); List<RoleVo> roleVos = rolePermissionMapper.selectRolesById(memberId); //3 转化数据 设置到simpleAuthorizationInfo中 Set<String> roles = new HashSet<>(); Set<String> permissions = new HashSet<>(); //4、将对应的用户权限名称对应·赋值 //如果验证成功,最终这里返回的信息authenticationInfo 的值与传入的第一个字段的值member相同 roleVos.forEach(roleVo -> { roles.add(roleVo.getName()); roleVo.getPermissions().forEach(permission -> { permissions.add(permission.getName()); }); }); simpleAuthorizationInfo.setRoles(roles); simpleAuthorizationInfo.setStringPermissions(permissions); return simpleAuthorizationInfo; } -
3、配置类配置
@Bean public UserRealm realm(HashedCredentialsMatcher hashedCredentialsMatcher) { UserRealm userRealm = new UserRealm(); // 注册到realm中 userRealm.setCredentialsMatcher(hashedCredentialsMatcher); return userRealm; } /** * 配置密码加密算法 * @return */ @Bean @Primary public HashedCredentialsMatcher hashedCredentialsMatcher(){ //以md5进行加密 HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(Md5Hash.ALGORITHM_NAME); //散列的次数,默认1次, 设置两次相当于 md5(md5("")); hashedCredentialsMatcher.setHashIterations(ShiroUtils.HASH_ITERATIONS); return hashedCredentialsMatcher; } -
4、前端使用的注解
注解 功能 说明 @RequiresRoles(重点) 已登录的用户需具有指定的角色才能访问 @RequiresPermissions(重点) 已登录的用户需具有指定的权限才能访问 @RequiresGuest 只有游客可以访问 @RequiresAuthentication 需要登录才能访问 @RequiresUser 已登录的用户或“记住我”的用户能访问 @RequiresRoles(重点)
@RestController @RequestMapping("/admin") public class AdminController { @GetMapping("/list") @RequiresRoles(value = {"admin", "dev"}, logical = Logical.OR) public String list() { return "查看列表信息"; } @RequiresPermissions({"view"}) @GetMapping("view") public String view() { return "查看列表信息"; } @PostMapping("/add") @RequiresRoles("dev") @RequiresPermissions({"add"}) public String save() { return "查看列表信息"; } }4、JWT基于用户身份验证
说明:jwt token 令牌 校验 安全性的问题 令牌失效 续命jwt 10有效期 刷新令,jwt参考
-
4.1、前端账号密码验证,向前端返回jssionId
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password); try { SecurityUtils.getSubject().login(usernamePasswordToken); } catch (UnknownAccountException | IncorrectCredentialsException uae) { throw new ControllerException(ResultCode.ACCOUNT_NOT_EXIST); } catch (LockedAccountException lae) { throw new ControllerException(ResultCode.SYSTEM_ERROR); } //获取会话中的id(相当于获取令牌) Serializable id = ShiroUtils.getSession().getId(); //将令牌响应回前端 return ResponseResult.success(id); -
4.2、校验jssionId(发起二次请求时),校验jssionId【继承DefaultWebSessionManager的自定类】
从请求头中获取jssionId
//主要定义了session的创建,启动,暂停与cookie的关联的定义 public class CustomSessionManager extends DefaultWebSessionManager { //定义jwit private static final String SHIRO_AUTH = "auth_token"; private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; public CustomSessionManager() { super(); } @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response) { //获取前端来的请求,并获取令牌id String id = WebUtils.toHttp(request).getHeader(SHIRO_AUTH); //如果请求头中有 token 则其值为sessionId if (!StringUtils.isEmpty(id)) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); return id; } else { //否则按默认规则从cookie取sessionId Serializable sessionId = super.getSessionId(request, response); return sessionId; } } } -
4.3、配置类的配置(注册与配置)
/** * 基于数据数据用户表验证 */ @Bean public UserRealm realm(HashedCredentialsMatcher hashedCredentialsMatcher) { UserRealm userRealm = new UserRealm(); // 注册到realm中 userRealm.setCredentialsMatcher(hashedCredentialsMatcher); return userRealm; } //配置请求session @Bean public CustomSessionManager webSessionManager(){ CustomSessionManager customSessionManager = new CustomSessionManager(); return customSessionManager; }
day(3-24)redis概论
1、redis概论
- 1.1、应用场景
-
缓冲
-
验证码
-
2、redis安装
-
1、window安装
-
2、linux安装
-
docker-compose文件
version: "3" services: redis-servier: image: redis:5 environment: - TZ=Asia/Shanghai ports: - 6379:6379 volumes: - ./redis/data:/data
-
3、redis文件配置
-
1、redis配置文件配置
spring: redis: host: 47.113.188.31 port: 6739 #指定数据库 database: 0 password: "" timeout: 3s #连接池配置 jedis: pool: #最大连接数 max-active: 10 #连接池最大存活数 max-idle: 8 #连接池最小存活数 min-idle: 2 -
2、配置类的配置(键和值的分别序列化)
@Bean public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) { return redisTemplate.opsForValue(); } @Bean public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){ RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); //配置序列化方式 /*键的序列化,当键为String类型的时候*/ StringRedisSerializer serializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(serializer); redisTemplate.setHashKeySerializer(serializer); /*值的序列化,当值为对象的时候*/ Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);/*普通对象序列化*/ redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);/*Map对象序列化*/ //将自定的RedisTemplate注入到容器中 redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; }user:uid:1:意思是user表,键值为1
4、redis基础使用
RedisTemplate:操作redsi
-
验证码
-
valueOperations.set("hello", "world"); // valueOperations.set("phone:1xxxxx", 123456, Duration.ofMinutes(1)); // valueOperations.set("phone:1xxxxx1111", 123456, 1, TimeUnit.MINUTES);
-
-
alueOperations.setIfAbsent(“hello”, “123”);如果键存在 则不设置 否则设置【分布式锁】
-
valueOperations.setIfPresent(“hello”,234);如果键不存在 就不设置值 否则设置值
-
valueOperations.getAndSet(“hello”, “修改”);获取旧值 设置新的值
-
Duration.ofMinutes(1)设置数据的过期时间
-
Long increment1 = valueOperations.increment(“distributed:user:id”, 2);自增 设置ID 可以用于分布式ID 【分布式id】,有自增因子
-
分布式id
-
自增 设置ID
-
本文介绍了Shiro框架在认证、加密和权限管理方面的应用,包括用户登录流程、自定义Realm实现、加密算法配置、权限分类及数据库表设计。同时,文章探讨了JWT令牌的安全验证,前端如何获取与使用token,以及Redis的配置和基础使用,如缓存、验证码等。
1300

被折叠的 条评论
为什么被折叠?



