最近项目上用到File类去创建文件夹和图片,在通过Nginx直接访问图片的时候,Nginx返回403没有访问权限的问题。


█文件权限

(1)查看文件权限

通过命令ls -l可以查看文件夹或文件的权限信息

FileSystem 设置用户 files权限_Nginx

drwxr-xr-x:

d:directory的开头字母,表示文件是一个目录。-表示文件。

rwxr-xr-x:9位标识,前三个标识表示当前文件拥有者拥有的权限,中间三个标识表示与文件拥有者所在同一个组内成员拥有的权限,最后三个标识表示其他人员拥有的权限。

r:read,读权限

w:write,写权限

x:execute,执行权限,即可以运行该文件(脚本等)

(2)更改文件权限

使用二进制表示,拥有权限用1表示,没有权限用0表示,则rwxr-xr-x可以表示为111101101。将三种用户的权限分开表示则为111 101 101,将各二进制转换成10进制为:7 5 5。

执行命令: chmod 权限值 文件,比如chmod 755 this_is_dirctory。

FileSystem 设置用户 files权限_文件权限_02

更详细的chmod介绍和使用,请戳《Linux chmod 命令 | 菜鸟教程

(3)文件需要存在

当对一个不存在的文件设置权限的时候,会报错。

FileSystem 设置用户 files权限_文件权限_03

(4)默认权限

当创建目录或者文件的时候,操作系统会分配默认权限。默认权限可以更改。

在我使用的操作系统上,目录的默认权限为:rwxr-xr-x

FileSystem 设置用户 files权限_文件权限_04

文件的默认权限为:rw-r--r--

FileSystem 设置用户 files权限_java_05


█Java创建文件并设置权限

使用File类创建文件。

package java.io;
public class File
    implements Serializable, Comparable<File>

(1)代码

代码的用意是在目录/upload下创建一个this_is_directory目录,以及this_is_file文件。并且给目录this_is_directory三种用户都分配福读、写、执行权限,给文件this_is_file三种用户都分配读、执行权限。

FileOutputStream out = null;
try {
    File dir = new File("/upload/this_is_directory");
    if (!dir.exists() && !dir.isDirectory()) {
        dir.setWritable(true, false);
        dir.setReadable(true, false);
        dir.setExecutable(true, false);
        dir.mkdirs();
    }

    File file = new File("/upload/this_is_file");
    file.setReadable(true, false);
    file.setExecutable(true, false);
    out = new FileOutputStream(file);
    //out.write(content);
    out.flush();
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (out!=null) {
        try {
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行上述代码,当查看目录和文件权限的时候,发现并不是如预期那样,而是使用的默认权限。问题是出在生成文件和分配权限代码的顺序错误了,即

dir.setWritable(true, false);
dir.setReadable(true, false);
dir.setExecutable(true, false);
dir.mkdirs();

正确的顺序应该为:

dir.mkdirs();
dir.setWritable(true, false);
dir.setReadable(true, false);
dir.setExecutable(true, false);

这里是因为当执行setWritable、setReadable、setExecutable方法的时候,会去给文件设置权限,而此时文件还不存在,所有权限不会生效。要等文件创建成功存在了之后才能设置权限。(文件不存在设置权限失败,即上面的第(3)条)

正确的代码:

FileOutputStream out = null;
try {
    File dir = new File("/upload/this_is_directory");
    if (!dir.exists() && !dir.isDirectory()) {
        dir.mkdirs();
        // 需要等文件夹创建了之后,再去设置权限
        dir.setWritable(true, false);
        dir.setReadable(true, false);
        dir.setExecutable(true, false);
    }

    File file = new File("/upload/this_is_file");
    out = new FileOutputStream(file);
    //out.write(content);
    out.flush();
    // 等文件创建之后,再设置权限
    file.setReadable(true, false);
    file.setExecutable(true, false);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (out!=null) {
        try {
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}