shiro 인증 구현에 대한 자세한 설명
이번에는 shiro 인증 구현에 대해 자세히 설명하겠습니다. shiro 인증 구현에 대한 주의사항은 무엇인가요?
액세스 제어라고도 하는 권한 부여는 누가 애플리케이션의 어떤 리소스에 액세스할 수 있는지 제어하는 것입니다(예: 페이지 액세스/데이터 편집/페이지 작업 등). 권한 부여에서 이해해야 하는 몇 가지 주요 개체(주제, 리소스, 권한 및 역할)가 있습니다.
주제
주체, 즉 애플리케이션에 접근하는 사용자는 Shiro에서 Subject를 사용하여 사용자를 나타냅니다. 사용자는 승인 후에만 해당 리소스에 액세스할 수 있습니다.
리소스
JSP 페이지 액세스, 특정 데이터 보기/편집, 비즈니스 메소드 액세스, 텍스트 인쇄 등과 같이 사용자가 애플리케이션에서 액세스할 수 있는 모든 것은 모두 리소스입니다. 사용자는 승인 후에만 접근할 수 있습니다.
권한
보안 정책의 원자 권한 부여 단위는 권한을 통해 사용자가 애플리케이션에서 특정 리소스를 작동할 수 있는 권한이 있는지 여부를 나타낼 수 있습니다. 즉, 권한은 사용자가 다음과 같은 애플리케이션의 특정 리소스에 액세스할 수 있는지 여부를 나타냅니다. 사용자 목록 페이지를 방문하세요
사용자 데이터 보기/추가/수정/삭제(즉, CRUD(추가, 확인, 수정, 삭제) 권한 제어가 많은 경우)
문서 등을 인쇄하세요. . .
위에서 알 수 있듯이 권한은 사용자가 특정 리소스를 조작할 수 있는 권한이 있는지, 즉 특정 리소스에 대한 작업이 허용되는지 여부를 나타내며, 누가 작업을 수행하는지를 반영하지는 않습니다. 따라서 앞으로는 사용자에게 권한을 부여해야 합니다. 즉, 어떤 사용자가 특정 리소스에 대해 어떤 작업(권한)을 수행할 수 있는지 정의하는 것이 필요하지만 구현자가 이를 제공하지는 않습니다.
Shiro는 대략적인 권한(예: 사용자 모듈의 모든 권한)과 세분화된 권한(특정 사용자, 즉 인스턴스 수준을 조작하는 권한)을 지원하며 이에 대해서는 이후 섹션에서 소개합니다.
역할
역할은 권한 집합으로 이해될 수 있는 일련의 작업을 나타냅니다. 일반적으로 사용자에게 권한 대신 역할을 부여합니다. 즉, 이러한 방식으로 사용자는 권한을 부여할 때 더 편리한 권한 집합을 가질 수 있습니다. . 일반적인 예로는 프로젝트 관리자, 기술 이사, CTO, 개발 엔지니어 등이 모두 역할이며 역할마다 권한 집합이 다릅니다.
암시적 역할: 즉, 역할을 통해 사용자에게 작업 권한이 있는지 직접 확인합니다. 예를 들어 응용 프로그램에서는 CTO, 기술 책임자 및 개발 엔지니어가 프린터를 사용할 수 없다고 가정합니다. 특정 날짜에 해당 기능을 애플리케이션에서 삭제해야 합니다. 또 다른 예는 애플리케이션에서 어느 날 갑자기 기술 책임자가 사용자를 볼 수 있고 권한을 볼 수 있다는 것입니다. 사용자 보기 및 권한 보기가 허용되지 않으며 관련 코드의 판단 논리에서 기술 책임자 역할을 삭제해야 합니다. 즉, 세분성 액세스 제어는 역할별로 더 대략적으로 수행됩니다. 수정으로 인해 여러 코드가 수정될 수 있습니다.
역할 표시: 권한을 사용하여 프로그램의 리소스에 액세스할 수 있는 사람을 제어합니다. 역할은 이러한 방식으로 리소스에 액세스할 수 없는 경우 해당 역할이 나타내는 권한 집합에서만 제거하면 됩니다. 더 많은 코드를 수정할 필요가 없습니다. 즉, 세분성은 리소스/인스턴스를 기반으로 합니다.
"역할 기반 접근 제어"와 "리소스 기반 접근 제어(Resource-Based Access Control)"에 대해 각각 구글 "RBAC"와 "RBAC 새로운 해석"을 검색해 보세요.
승인 방법
Shiro는 세 가지 인증 방법을 지원합니다:
프로그래밍 방식: if/else 인증 코드 블록을 작성하여 완료:
Subject subject = SecurityUtils.getSubject(); if(subject.hasRole(“admin”)) { //有权限 } else { //无权限 }
주석: 실행된 Java 메소드에 해당 주석을 배치하여 완료됩니다.
@RequiresRoles("admin") public void hello() { //有权限 }
허가가 없으면 해당 예외가 발생합니다.
JSP/GSP 태그: 해당 태그를 통해 JSP/GSP 페이지를 완성하세요:
<shiro:hasRole name="admin"> <!— 有权限 —> </shiro:hasRole>
다음 섹션에서는 이를 사용하는 방법을 자세히 설명합니다.
승인
역할 기반 액세스 제어(암시적 역할)
1. ini
구성 파일에서 사용자가 소유한 역할(shiro-role.ini)을 구성합니다.
[users] zhang=123,role1,role2 wang=123,role1
规则即:“用户名=密码,角色1,角色2”,如果需要在应用中判断用户是否有相应角色,就需要在相应的Realm中返回角色信息,也就是说Shiro不负责维护用户-角色信息,需要应用提供,Shiro只是提供相应的接口方便验证,后续会介绍如何动态的获取用户角色。
2、测试用例(com.github.zhangkaitao.shiro.chapter3.RoleTest)
@Test public void testHasRole() { login("classpath:shiro-role.ini", "zhang", "123"); //判断拥有角色:role1 Assert.assertTrue(subject().hasRole("role1")); //判断拥有角色:role1 and role2 Assert.assertTrue(subject().hasAllRoles(Arrays.asList("role1", "role2"))); //判断拥有角色:role1 and role2 and !role3 boolean[] result = subject().hasRoles(Arrays.asList("role1", "role2", "role3")); Assert.assertEquals(true, result[0]); Assert.assertEquals(true, result[1]); Assert.assertEquals(false, result[2]); }
Shiro提供了hasRole/hasRole用于判断用户是否拥有某个角色/某些权限;但是没有提供如hashAnyRole用于判断是否有某些权限中的某一个。
@Test(expected = UnauthorizedException.class) public void testCheckRole() { login("classpath:shiro-role.ini", "zhang", "123"); //断言拥有角色:role1 subject().checkRole("role1"); //断言拥有角色:role1 and role3 失败抛出异常 subject().checkRoles("role1", "role3"); }
Shiro提供的checkRole/checkRoles和hasRole/hasAllRoles不同的地方是它在判断为假的情况下会抛出UnauthorizedException异常。
到此基于角色的访问控制(即隐式角色)就完成了,这种方式的缺点就是如果很多地方进行了角色判断,但是有一天不需要了那么就需要修改相应代码把所有相关的地方进行删除;这就是粗粒度造成的问题。
基于资源的访问控制(显示角色)
1、在ini配置文件配置用户拥有的角色及角色-权限关系(shiro-permission.ini)
[users] zhang=123,role1,role2 wang=123,role1 [roles] role1=user:create,user:update role2=user:create,user:delete
规则:“用户名=密码,角色1,角色2”“角色=权限1,权限2”,即首先根据用户名找到角色,然后根据角色再找到权限;即角色是权限集合;Shiro同样不进行权限的维护,需要我们通过Realm返回相应的权限信息。只需要维护“用户——角色”之间的关系即可。
2、测试用例(com.github.zhangkaitao.shiro.chapter3.PermissionTest)
@Test public void testIsPermitted() { login("classpath:shiro-permission.ini", "zhang", "123"); //判断拥有权限:user:create Assert.assertTrue(subject().isPermitted("user:create")); //判断拥有权限:user:update and user:delete Assert.assertTrue(subject().isPermittedAll("user:update", "user:delete")); //判断没有权限:user:view Assert.assertFalse(subject().isPermitted("user:view")); }
Shiro提供了isPermitted和isPermittedAll用于判断用户是否拥有某个权限或所有权限,也没有提供如isPermittedAny用于判断拥有某一个权限的接口。
@Test(expected = UnauthorizedExceptionclass) public void testCheckPermission () { login("classpath:shiro-permissionini", "zhang", "123"); //断言拥有权限:user:create subject().checkPermission("user:create"); //断言拥有权限:user:delete and user:update subject().checkPermissions("user:delete", "user:update"); //断言拥有权限:user:view 失败抛出异常 subject().checkPermissions("user:view"); }
但是失败的情况下会抛出UnauthorizedException异常。
到此基于资源的访问控制(显示角色)就完成了,也可以叫基于权限的访问控制,这种方式的一般规则是“资源标识符:操作”,即是资源级别的粒度;这种方式的好处就是如果要修改基本都是一个资源级别的修改,不会对其他模块代码产生影响,粒度小。但是实现起来可能稍微复杂点,需要维护“用户——角色,角色——权限(资源:操作)”之间的关系。
Permission
字符串通配符权限
规则:“资源标识符:操作:对象实例ID” 即对哪个资源的哪个实例可以进行什么操作。其默认支持通配符权限字符串,“:”表示资源/操作/实例的分割;“,”表示操作的分割;“*”表示任意资源/操作/实例。
1、单个资源单个权限
subject().checkPermissions("system:user:update");
用户拥有资源“system:user”的“update”权限。
2、单个资源多个权限
ini配置文件
role41=system:user:update,system:user:delete
然后通过如下代码判断
subject().checkPermissions("system:user:update", "system:user:delete");
用户拥有资源“system:user”的“update”和“delete”权限。如上可以简写成:
ini配置(表示角色4拥有system:user资源的update和delete权限)
role42="system:user:update,delete"
接着可以通过如下代码判断
subject().checkPermissions("system:user:update,delete");
通过“system:user:update,delete”验证"system:user:update, system:user:delete"是没问题的,但是反过来是规则不成立。
3、单个资源全部权限
ini配置
role51="system:user:create,update,delete,view"
然后通过如下代码判断
subject().checkPermissions("system:user:create,delete,update:view");
用户拥有资源“system:user”的“create”、“update”、“delete”和“view”所有权限。如上可以简写成:
ini配置文件(表示角色5拥有system:user的所有权限)
role52=system:user:*
也可以简写为(推荐上边的写法):
role53=system:user
然后通过如下代码判断
subject().checkPermissions("system:user:*"); subject().checkPermissions("system:user");
通过“system:user:*”验证“system:user:create,delete,update:view”可以,但是反过来是不成立的。
4、所有资源全部权限
ini配置
role61=*:view
然后通过如下代码判断
subject().checkPermissions("user:view");
用户拥有所有资源的“view”所有权限。假设判断的权限是“"system:user:view”,那么需要“role5=*:*:view”这样写才行。
5、实例级别的权限
5.1、单个实例单个权限
ini配置
role71=user:view:1
对资源user的1实例拥有view权限。
然后通过如下代码判断
subject().checkPermissions("user:view:1");
5.2、单个实例多个权限
ini配置
role72="user:update,delete:1"
对资源user的1实例拥有update、delete权限。
然后通过如下代码判断
subject().checkPermissions("user:delete,update:1"); subject().checkPermissions("user:update:1", "user:delete:1");
5.3、单个实例所有权限
ini配置
role73=user:*:1
对资源user的1实例拥有所有权限。
然后通过如下代码判断
subject().checkPermissions("user:update:1", "user:delete:1", "user:view:1");
5.4、所有实例单个权限
ini配置
role74=user:auth:*
对资源user的1实例拥有所有权限。
然后通过如下代码判断
subject().checkPermissions("user:auth:1", "user:auth:2");
5.5、所有实例所有权限
ini配置
role75=user:*:*
对资源user的1实例拥有所有权限。
然后通过如下代码判断
subject().checkPermissions("user:view:1", "user:auth:2");
6、Shiro对权限字符串缺失部分的处理
如“user:view”等价于“user:view:*”;而“organization”等价于“organization:*”或者“organization:*:*”。可以这么理解,这种方式实现了前缀匹配。
另外如“user:*”可以匹配如“user:delete”、“user:delete”可以匹配如“user:delete:1”、“user:*:1”可以匹配如“user:view:1”、“user”可以匹配“user:view”或“user:view:1”等。即*可以匹配所有,不加*可以进行前缀匹配;但是如“*:view”不能匹配“system:user:view”,需要使用“*:*:view”,即后缀匹配必须指定前缀(多个冒号就需要多个*来匹配)。
7、WildcardPermission
如下两种方式是等价的:
subject().checkPermission("menu:view:1"); subject().checkPermission(new WildcardPermission("menu:view:1"));
因此没什么必要的话使用字符串更方便。
8、性能问题
通配符匹配方式比字符串相等匹配来说是更复杂的,因此需要花费更长时间,但是一般系统的权限不会太多,且可以配合缓存来提供其性能,如果这样性能还达不到要求我们可以实现位操作算法实现性能更好的权限匹配。另外实例级别的权限验证如果数据量太大也不建议使用,可能造成查询权限及匹配变慢。可以考虑比如在sql查询时加上权限字符串之类的方式在查询时就完成了权限匹配。
流程如下:
1、首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer;
2、Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver把字符串转换成相应的Permission实例;
3、在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;
4、Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否则返回false表示授权失败。
ModularRealmAuthorizer进行多Realm匹配流程:
1、首先检查相应的Realm是否实现了实现了Authorizer;
2、如果实现了Authorizer,那么接着调用其相应的isPermitted*/hasRole*接口进行匹配;
3、如果有一个Realm匹配那么将返回true,否则返回false。
如果Realm进行授权的话,应该继承AuthorizingRealm,其流程是:
1.1、如果调用hasRole*,则直接获取AuthorizationInfo.getRoles()与传入的角色比较即可;
1.2、首先如果调用如isPermitted(“user:view”),首先通过PermissionResolver将权限字符串转换成相应的Permission实例,默认使用WildcardPermissionResolver,即转换为通配符的WildcardPermission;
2、通过AuthorizationInfo.getObjectPermissions()得到Permission实例集合;通过AuthorizationInfo. getStringPermissions()得到字符串集合并通过PermissionResolver解析为Permission实例;然后获取用户的角色,并通过RolePermissionResolver解析角色对应的权限集合(默认没有实现,可以自己提供);
3、接着调用Permission. implies(Permission p)逐个与传入的权限比较,如果有匹配的则返回true,否则false。
Authorizer、PermissionResolver及RolePermissionResolver
Authorizer的职责是进行授权(访问控制),是Shiro API中授权核心的入口点,其提供了相应的角色/权限判断接口,具体请参考其Javadoc。SecurityManager继承了Authorizer接口,且提供了ModularRealmAuthorizer用于多Realm时的授权匹配。PermissionResolver用于解析权限字符串到Permission实例,而RolePermissionResolver用于根据角色解析相应的权限集合。
我们可以通过如下ini配置更改Authorizer实现:
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer securityManager.authorizer=$authorizer
对于ModularRealmAuthorizer,相应的AuthorizingSecurityManager会在初始化完成后自动将相应的realm设置进去,我们也可以通过调用其setRealms()方法进行设置。对于实现自己的authorizer可以参考ModularRealmAuthorizer实现即可,在此就不提供示例了。
设置ModularRealmAuthorizer的permissionResolver,其会自动设置到相应的Realm上(其实现了PermissionResolverAware接口),如:
permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver authorizer.permissionResolver=$permissionResolver
设置ModularRealmAuthorizer的rolePermissionResolver,其会自动设置到相应的Realm上(其实现了RolePermissionResolverAware接口),如:
rolePermissionResolver=com.github.zhangkaitao.shiro.chapter3.permission.MyRolePermissionResolver authorizer.rolePermissionResolver=$rolePermissionResolver
示例
1、ini配置(shiro-authorizer.ini)
[main] #自定义authorizer authorizer=org.apache.shiro.authz.ModularRealmAuthorizer #自定义permissionResolver #permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver permissionResolver=com.github.zhangkaitao.shiro.chapter3.permission.BitAndWildPermissionResolver authorizer.permissionResolver=$permissionResolver #自定义rolePermissionResolver rolePermissionResolver=com.github.zhangkaitao.shiro.chapter3.permission.MyRolePermissionResolver 1authorizer.rolePermissionResolver=$rolePermissionResolver securityManager.authorizer=$authorizer
#自定义realm 一定要放在securityManager.authorizer赋值之后(因为调用setRealms会将realms设置给authorizer,并给各个Realm设置permissionResolver和rolePermissionResolver) realm=com.github.zhangkaitao.shiro.chapter3.realm.MyRealm securityManager.realms=$realm
设置securityManager 的realms一定要放到最后,因为在调用SecurityManager.setRealms时会将realms设置给authorizer,并为各个Realm设置permissionResolver和rolePermissionResolver。另外,不能使用IniSecurityManagerFactory创建的IniRealm,因为其初始化顺序的问题可能造成后续的初始化Permission造成影响。
2、定义BitAndWildPermissionResolver及BitPermission
BitPermission用于实现位移方式的权限,如规则是:
权限字符串格式:+资源字符串+权限位+实例ID;以+开头中间通过+分割;权限:0 表示所有权限;1 新增(二进制:0001)、2 修改(二进制:0010)、4 删除(二进制:0100)、8 查看(二进制:1000);如 +user+10 表示对资源user拥有修改/查看权限。
public class BitPermission implements Permission { private String resourceIdentify; private int permissionBit; private String instanceId; public BitPermission(String permissionString) { String[] array = permissionString.split("\\+"); if(array.length > 1) { resourceIdentify = array[1]; } if(StringUtils.isEmpty(resourceIdentify)) { resourceIdentify = "*"; } if(array.length > 2) { permissionBit = Integer.valueOf(array[2]); } if(array.length > 3) { instanceId = array[3]; } if(StringUtils.isEmpty(instanceId)) { instanceId = "*"; } } @Override public boolean implies(Permission p) { if(!(p instanceof BitPermission)) { return false; } BitPermission other = (BitPermission) p; if(!("*".equals(this.resourceIdentify) || this.resourceIdentify.equals(other.resourceIdentify))) { return false; } if(!(this.permissionBit ==0 || (this.permissionBit & other.permissionBit) != 0)) { return false; } if(!("*".equals(this.instanceId) || this.instanceId.equals(other.instanceId))) { return false; } return true; } } Permission接口提供了boolean implies(Permission p)方法用于判断权限匹配的; public class BitAndWildPermissionResolver implements PermissionResolver { @Override public Permission resolvePermission(String permissionString) { if(permissionString.startsWith("+")) { return new BitPermission(permissionString); } return new WildcardPermission(permissionString); } }
BitAndWildPermissionResolver实现了PermissionResolver接口,并根据权限字符串是否以“+”开头来解析权限字符串为BitPermission或WildcardPermission。
3、定义MyRolePermissionResolver
RolePermissionResolver用于根据角色字符串来解析得到权限集合。
public class MyRolePermissionResolver implements RolePermissionResolver { @Override public Collection<Permission> resolvePermissionsInRole(String roleString) { if("role1".equals(roleString)) { return Arrays.asList((Permission)new WildcardPermission("menu:*")); } return null; } }
此处的实现很简单,如果用户拥有role1,那么就返回一个“menu:*”的权限。
4、自定义Realm
public class MyRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addRole("role1"); authorizationInfo.addRole("role2"); authorizationInfo.addObjectPermission(new BitPermission("+user1+10")); authorizationInfo.addObjectPermission(new WildcardPermission("user1:*")); authorizationInfo.addStringPermission("+user2+10"); authorizationInfo.addStringPermission("user2:*"); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //和com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1. getAuthenticationInfo代码一样,省略 } }
此时我们继承AuthorizingRealm而不是实现Realm接口;推荐使用AuthorizingRealm,因为:
AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token):表示获取身份验证信息;
AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals):表示根据用户身份获取授权信息。
这种方式的好处是当只需要身份验证时只需要获取身份验证信息而不需要获取授权信息。对于AuthenticationInfo和AuthorizationInfo请参考其Javadoc获取相关接口信息。
另外我们可以使用JdbcRealm,需要做的操作如下
1、执行sql/ shiro-init-data.sql 插入相关的权限数据;
2、使用shiro-jdbc-authorizer.ini配置文件,需要设置jdbcRealm.permissionsLookupEnabled为true来开启权限查询。
此次还要注意就是不能把我们自定义的如“+user1+10”配置到INI配置文件,即使有IniRealm完成,因为IniRealm在new完成后就会解析这些权限字符串,默认使用了WildcardPermissionResolver完成,即此处是一个设计权限,如果采用生命周期(如使用初始化方法)的方式进行加载就可以解决我们自定义permissionResolver的问题。
5、测试用例
public class AuthorizerTest extends BaseTest { @Test public void testIsPermitted() { login("classpath:shiro-authorizer.ini", "zhang", "123"); //判断拥有权限:user:create Assert.assertTrue(subject().isPermitted("user1:update")); Assert.assertTrue(subject().isPermitted("user2:update")); //通过二进制位的方式表示权限 Assert.assertTrue(subject().isPermitted("+user1+2"));//新增权限 Assert.assertTrue(subject().isPermitted("+user1+8"));//查看权限 Assert.assertTrue(subject().isPermitted("+user2+10"));//新增及查看 Assert.assertFalse(subject().isPermitted("+user1+4"));//没有删除权限 Assert.assertTrue(subject().isPermitted("menu:view"));//通过MyRolePermissionResolver解析得到的权限 } }
通过如上步骤可以实现自定义权限验证了。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
위 내용은 shiro 인증 구현에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

현재 Win10 Enterprise Edition 2016 Long-term Service Edition을 더 이상 사용하지 않으려면 Professional Edition으로 전환할 수도 있습니다. 방법도 매우 간단합니다. 일부 콘텐츠를 변경하고 시스템 이미지만 설치하면 됩니다. win10 enterprise 버전 2016 장기서비스 버전을 professional 버전으로 변경하는 방법 1. win+R 누른 후 "regedit" 입력 2. 위 주소창에 Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT 경로를 직접 붙여넣기 \CurrentVersion3 , EditionID를 찾아 내용을 "professional"로 바꿔 확인합니다.

C++의 모드 함수에 대한 자세한 설명 통계에서 모드는 데이터 집합에서 가장 자주 나타나는 값을 의미합니다. C++ 언어에서는 모드 함수를 작성하여 모든 데이터 세트에서 모드를 찾을 수 있습니다. 모드 기능은 다양한 방법으로 구현될 수 있으며, 일반적으로 사용되는 두 가지 방법을 아래에서 자세히 소개합니다. 첫 번째 방법은 해시 테이블을 사용하여 각 숫자의 발생 횟수를 계산하는 것입니다. 먼저, 각 숫자를 키로, 발생 횟수를 값으로 사용하여 해시 테이블을 정의해야 합니다. 그런 다음 주어진 데이터 세트에 대해 다음을 실행합니다.

Windows 운영 체제는 세계에서 가장 인기 있는 운영 체제 중 하나이며, 새로운 버전의 Win11이 많은 주목을 받았습니다. Win11 시스템에서 관리자 권한을 얻는 것은 사용자가 시스템에서 더 많은 작업과 설정을 수행할 수 있도록 하는 중요한 작업입니다. 이번 글에서는 Win11 시스템에서 관리자 권한을 얻는 방법과 권한을 효과적으로 관리하는 방법을 자세히 소개하겠습니다. Win11 시스템에서 관리자 권한은 로컬 관리자와 도메인 관리자의 두 가지 유형으로 나뉩니다. 로컬 관리자는 로컬 컴퓨터에 대한 모든 관리 권한을 갖습니다.

OracleSQL의 나눗셈 연산에 대한 자세한 설명 OracleSQL에서 나눗셈 연산은 두 숫자를 나눈 결과를 계산하는 데 사용되는 일반적이고 중요한 수학 연산입니다. 나누기는 데이터베이스 쿼리에 자주 사용되므로 OracleSQL에서 나누기 작업과 사용법을 이해하는 것은 데이터베이스 개발자에게 필수적인 기술 중 하나입니다. 이 기사에서는 OracleSQL의 나누기 작업 관련 지식을 자세히 설명하고 독자가 참고할 수 있는 특정 코드 예제를 제공합니다. 1. OracleSQL의 Division 연산

C++의 나머지 함수에 대한 자세한 설명 C++에서는 나머지 연산자(%)를 사용하여 두 숫자를 나눈 나머지를 계산합니다. 피연산자가 모든 정수 유형(char, short, int, long 등 포함) 또는 부동 소수점 숫자 유형(예: float, double)일 수 있는 이진 연산자입니다. 나머지 연산자는 피제수와 동일한 부호를 가진 결과를 반환합니다. 예를 들어 정수의 나머지 연산의 경우 다음 코드를 사용하여 구현할 수 있습니다. inta=10;intb=3;

Linux 시스템 호출 system() 함수에 대한 자세한 설명 시스템 호출은 Linux 운영 체제에서 매우 중요한 부분으로 시스템 커널과 상호 작용하는 방법을 제공합니다. 그 중 system() 함수는 흔히 사용되는 시스템 호출 함수 중 하나이다. 이 기사에서는 system() 함수의 사용법을 자세히 소개하고 해당 코드 예제를 제공합니다. 시스템 호출의 기본 개념 시스템 호출은 사용자 프로그램이 운영 체제 커널과 상호 작용하는 방법입니다. 사용자 프로그램은 시스템 호출 기능을 호출하여 운영 체제를 요청합니다.

PHP의 모듈로 연산자(%)는 두 숫자를 나눈 나머지를 구하는 데 사용됩니다. 이 글에서는 모듈로 연산자의 역할과 사용법을 자세히 논의하고 독자의 이해를 돕기 위해 구체적인 코드 예제를 제공합니다. 1. 모듈로 연산자의 역할 수학에서는 정수를 다른 정수로 나누면 몫과 나머지가 나옵니다. 예를 들어 10을 3으로 나누면 몫은 3이고 나머지는 1입니다. 이 나머지를 얻기 위해 모듈로 연산자가 사용됩니다. 2. 모듈러스 연산자의 사용법 PHP에서는 모듈러스를 나타내기 위해 % 기호를 사용합니다.

Linux의 컬 명령에 대한 자세한 설명 요약: 컬은 서버와의 데이터 통신에 사용되는 강력한 명령줄 도구입니다. 이 글에서는 컬 명령어의 기본적인 사용법을 소개하고, 독자들이 명령어를 더 잘 이해하고 적용할 수 있도록 실제 코드 예제를 제공할 것입니다. 1. 컬이란 무엇인가? 컬은 다양한 네트워크 요청을 보내고 받는 데 사용되는 명령줄 도구입니다. HTTP, FTP, TELNET 등과 같은 다중 프로토콜을 지원하며 파일 업로드, 파일 다운로드, 데이터 전송, 프록시와 같은 풍부한 기능을 제공합니다.
