在Springboot整合SpringSecurity 02-使用自定义登陆页面中我们已经学会了自定义自己的登陆页面了。
下面让我们继续学习SpringSecurity的权限控制。
本系列的按顺序写的,如果对于某些代码不清楚,请看下前面的几篇文章。
Springboot整合SpringSecurity 01-使用入门
Springboot整合SpringSecurity 02-使用自定义登陆页面
Springboot整合SpringSecurity 03-访问权限控制
Springboot整合SpringSecurity 04-启用登出logout功能
Springboot整合SpringSecurity 05-使用JDBC实现认证和授权
Springboot整合SpringSecurity 06-登陆扩展之自定义登陆验证逻辑
Springboot整合SpringSecurity 07-方法访问权限控制
通常我们的网页都是需要引用静态css,images等资源的。所以这里我们模拟平常的开发场景。
在static/css目录下面创建一个test.css。内容如下:
.error {
color: red;
}
.username {
color: gray;
}
我们在我们自定义的login.html登陆页面里面引入这些静态资源。
This is My Login Page
package com.demo.spring.security.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author flw
*/
@Controller
public class HelloController {
@GetMapping("hello")
public String hello() {
return "hello";
}
@GetMapping("login")
public String login(@RequestParam(required = false) String error,
@RequestParam(required = false) String logout,
Model model) {
if (error != null) {
model.addAttribute("error", "error");
}
if (logout != null) {
model.addAttribute("logout", "logout");
}
return "login";
}
@GetMapping("/common/hello")
@ResponseBody
public String common() {
return "common";
}
@GetMapping("/user/hello")
@ResponseBody
public String user() {
return "user";
}
@GetMapping("/admin/hello")
@ResponseBody
public String admin() {
return "admin";
}
}
这里面我们额外创建了三个接口。/common/hello,/user/hello,/admin/hello
用来等下我们设置权限访问使用。
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withDefaultPasswordEncoder().username("user")
.password("user").roles("USER").build());
manager.createUser(User.withDefaultPasswordEncoder().username("admin")
.password("admin").roles("ADMIN").build());
manager.createUser(User.withDefaultPasswordEncoder().username("dba")
.password("dba").roles("DBA","USER").build());
return manager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/static/**", "/common/**","/login/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").access("hasRole('USER') and hasRole('DBA')")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
userDetailsService(): 这里面我们创建了三个用户,user只具有USER权限,admin只具有ADMIN权限,dba具体USER和DBA两个权限。
configure(HttpSecurity http): 这里面我们配置了/static/** 和/common/** 以及 "/login/** 三个路径的请求不需要任何权限,连登陆都不需要。 /admin/** 的请求需要ADMIN权限, /user/**的请求取药USER和DBA两个权限都是存在才能访问。
http://localhost:10022/security/common/hello
在浏览器输入后直接可以返回common字符串。说明/common/** 路径的请求不需要任何权限,甚至都不用登陆就可以访问。
http://localhost:10022/security/admin/hello
可以看到我们跳转到了登陆页面,通过F12可以看到我们的test.css被放行了,说明静态资源可以访问。
然后我们输入admin/admin的账号密码。
可以正常访问到http://localhost:10022/security/admin/hello,并返回admin字符串。
然后我们访问/user/hello的接口再试试。
http://localhost:10022/security/admin/hello
可以看到浏览器上面返回报错:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Sep 12 21:06:56 CST 2019
There was an unexpected error (type=Forbidden, status=403).
Forbidden
请求被forbidden掉了,证明admin没有/user/hello的访问权限。
首先我们继续回到登录
http://localhost:10022/security/login
输入user/user
这时候可能页面报错,不用担心,这是因为我们没有设置默认的登陆成功跳转页面。
而这次我们又是直接进入的登陆页面,所以登陆成功后没有成功的跳转页面,导致404。
登陆完成后,我们在浏览器中请求/user/hello接口
http://localhost:10022/security/user/hello
结果依然是403,因为我们设置了 /user/** 的请求需要同时 具有DBA和USER的权限。所以user用户还是不符合要求。
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Sep 12 21:12:30 CST 2019
There was an unexpected error (type=Forbidden, status=403).
Forbidden
下面我们继续回到登陆页面,使用dba/dba的账号密码登陆。
然后继续访问http://localhost:10022/security/user/hello