授权管理和自定义403页面
- Spring EL 权限表达式
表达式 | 描述 |
---|---|
permitAll() | 总是返回true,表示允许所有访问(认证不认证都可访问 URL或方法) |
denyAll() | 总是返回false,表示拒绝所有访问(永远访问不到指定的 URL或方法) |
isAnonymous() | 当前用户是一个匿名用户(未登录用户)允许访问,返回true |
isRememberMe() | 当前用户是通过Remember-Me自动登录的允许访问,返回true |
isAuthenticated() | 当前用户是已经登录认证成功的允许访问(包含了rememberMe自动登录的),返回true |
isFullyAuthenticated() | 如果当前用户既不是一个匿名用户,同时也不是通过Remember-Me自动登录的,则允许访问(可以理解为通过页面输入帐户信息认证的) |
hasRole(String role) | 当前用户拥有指定角色权限的允许访问,返回true。注意: 指定的角色名(如: ADMIN ) SpringSecurity 底层会在前面拼接 ROLE_ 字符串,所以在UserDetailsService实现类,数据库返回的角色名要有ROLE_ADMIN |
hasAnyRole([role1, role2]) | 多个角色以逗号分隔的字符串。如果当前用户拥有指定角色中的任意一个则允许访问,返回true |
hasAuthority(String authority) | 当前用户拥有指定权限标识的允许访问,返回true。注意:和 hasRole区别是, hasAuthority 不会在前面拼接 ROLE_ 字符串 |
hasAnyAuthority([auth1,auth2]) | 多个权限标识是以逗号分隔的字符串。如果当前用户拥有指定权限标识中的任意一个则允许访问,返回true |
hasIpAddress("192.168.1.1/29") | 限制指定IP或指定范围内的IP才可以访问 |
- 代码案例
@Component("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(!"admin".equalsIgnoreCase(username)) {
throw new UsernameNotFoundException("用户名或密码错误");
}
String password = passwordEncoder.encode("admin");
return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN"));
}
}
# security配置类
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginProcessingUrl("/login")
.successHandler(customAuthenticationSuccessHandler)
.failureHandler(customAuthenticationFailureHandler)
.defaultSuccessUrl("/success").permitAll()
.and().authorizeRequests()
.antMatchers("/test1").hasRole("admin") // 该接口需要role_admin权限
.antMatchers(HttpMethod.GET, "/role").hasAuthority("sys:role") // 拥有sys:role权限就可以访问get方式的/role
.antMatchers(HttpMethod.GET, "/permission").access("hasAuthority('sys:permission') or hasAnyRole('ADMIN')") // 拥有sys:permission或者admin
.antMatchers("/test").permitAll() // 不需要认证就能访问
.anyRequest().authenticated() // 其他请求需要认证
.and().csrf().disable();
}
-
测试test1
-
自定义403页面
/resource/static目录下新建403.html
# security配置类中添加如下
http.exceptionHandling().accessDeniedPage("/403.html");
# 新建403.scss
# 在链接1中获取到scss代码,复制到403.scss中
# 用vscode打开,下载插件Live Sass Compiler和Live Server
# 点击vscode右下角的Watch Sass进行转换,转为css
# 将css和js引入到html中
# 将html复制到/resource/static路径下
- html模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>403</title>
<style>
@import url("https://fonts.googleapis.com/css?family=Share+Tech+Mono|Montserrat:700");
* {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
box-sizing: border-box;
color: inherit;
}
body {
background-image: linear-gradient(120deg, #4f0088 0%, #000000 100%);
height: 100vh;
}
h1 {
font-size: 45vw;
text-align: center;
position: fixed;
width: 100vw;
z-index: 1;
color: rgba(255, 255, 255, 0.1490196078);
text-shadow: 0 0 50px rgba(0, 0, 0, 0.07);
top: 50%;
transform: translateY(-50%);
font-family: "Montserrat", monospace;
}
div {
background: rgba(0, 0, 0, 0);
width: 70vw;
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
padding: 30px 30px 10px;
box-shadow: 0 0 150px -20px rgba(0, 0, 0, 0.5);
z-index: 3;
}
P {
font-family: "Share Tech Mono", monospace;
color: #f5f5f5;
margin: 0 0 20px;
font-size: 17px;
line-height: 1.2;
}
span {
color: #f0c674;
}
i {
color: #8abeb7;
}
div a {
text-decoration: none;
}
b {
color: #81a2be;
}
a.avatar {
position: fixed;
bottom: 15px;
right: -100px;
-webkit-animation: slide 0.5s 4.5s forwards;
animation: slide 0.5s 4.5s forwards;
display: block;
z-index: 4;
}
a.avatar img {
border-radius: 100%;
width: 44px;
border: 2px solid white;
}
@-webkit-keyframes slide {
from {
right: -100px;
transform: rotate(360deg);
opacity: 0;
}
to {
right: 15px;
transform: rotate(0deg);
opacity: 1;
}
}
@keyframes slide {
from {
right: -100px;
transform: rotate(360deg);
opacity: 0;
}
to {
right: 15px;
transform: rotate(0deg);
opacity: 1;
}
}
</style>
</head>
<body>
<h1>403</h1>
<div><p>> <span>ERROR CODE</span>: "<i>HTTP 403 Forbidden</i>"</p>
<p>> <span>ERROR DESCRIPTION</span>: "<i>Access Denied. You Do Not Have The Permission To Access This Page On This Server</i>"</p>
<p>> <span>ERROR POSSIBLY CAUSED BY</span>: [<b>execute access forbidden, read access forbidden, write access forbidden, ssl required, ssl 128 required, ip address rejected, client certificate required, site access denied, too many users, invalid configuration, password change, mapper denied access, client certificate revoked, directory listing denied, client access licenses exceeded, client certificate is untrusted or invalid, client certificate has expired or is not yet valid, passport logon failed, source access denied, infinite depth is denied, too many requests from the same client ip</b>...]</p>
<p>> <span>SOME PAGES ON THIS SERVER THAT YOU DO HAVE PERMISSION TO ACCESS</span>: [<a href="/">Home Page</a>, <a href="/">About Us</a>, <a href="/">Contact Us</a>, <a href="/">Blog</a>...]</p><p>> <span>HAVE A NICE DAY SIR AXLEROD :-)</span></p>
</div>
<script>
var str = document.getElementsByTagName('div')[0].innerHTML.toString();
var i = 0;
document.getElementsByTagName('div')[0].innerHTML = "";
setTimeout(function() {
var se = setInterval(function() {
i++;
document.getElementsByTagName('div')[0].innerHTML = str.slice(0, i) + "|";
if (i == str.length) {
clearInterval(se);
document.getElementsByTagName('div')[0].innerHTML = str;
}
}, 10);
},0);
</script>
</body>
</html>