使用spring boot和spring security进行用户权限验证
转自:https://segmentfault.com/a/1190000013057238#articleHeader1
(sp:以下是实践记录。)
1.创建spring boot项目 选择如下项:
创建TestController.java类和test.html页面 指定初次访问的页面
TestController.java
package com.hjl.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class TestController {
@RequestMapping(value = "/")
public String login( ) {
return "test";
}
}
test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
这是一个测试授权的user用户跳转的页面!
</body>
</html>
2.启动项目 访问:http://localhost:8080/
这是security默认帮我们实现的功能,默认用户是user,密码已经打印在控制台中。你也可以自定义登录页面。
登录成功是这样
- 自定义授权
3.1添加自定义用户
实际上我们项目之所有具有授权功能,是security框架帮我们实现的。也就是WebSecurityConfigurerAdapter这个适配器完成,如果想要改变其默认行为,那可以重写该适配器中的一些方法。
创建AuthConfig.java类。
package com.hjl.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* 自定义身份验证类(用于重写WebSecurityConfigurerAdapter默认配置)
* @Configuration 表示这是一个配置类
* @EnableWebSecurity 允许security
* configure() 该方法重写了父类的方法,用于添加用户与角色
* */
@Configuration
@EnableWebSecurity
public class AuthConfig extends WebSecurityConfigurerAdapter{
/**
* 重写该方法,添加自定义用户
* */
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
//inMemoryAuthentication 从内存中获取
//密码进行加密
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("admin")).roles("ADMIN")
.and()
.withUser("user").password(new BCryptPasswordEncoder().encode("user")).roles("USER");
}
}
重启服务访问 http://localhost:8080/ 就可以输入自定义的用户密码登录。
3.2 提供服务
创建UserController.java和AdminController.java
UserController.java
package com.hjl.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user")
public String user() {
return "user用户";
}
}
AdminController.java
package com.hjl.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AdminController {
@GetMapping("/admin")
public String admin() {
return "admin用户";
}
}
在AuthConfig.java中配置权限
添加以下代码:
/**
* 重写该方法,设定用户访问权限
* 用户身份可以访问 订单相关API
* */
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN") //管理员权限
.antMatchers("/user/**").hasRole("USER") //用户权限
.antMatchers("/").hasRole("USER") //用户权限
.antMatchers("/login").permitAll()
.and()
.formLogin();
//super.configure(http);
}
重启服务进行登录
- 如果使用admin账号登录则users相关API和admin相关API都可以访问
- 如果使用user账号登录则只能访问user相关API
4.自定义登录页面
默认情况下,当用户没有登录就去访问受保护资源时,系统会默认请求/login(get方式),这时重定向到登录页(spring security自带)。当输入用户名密码点击登录按钮的时候,系统会请求/login(post方式)。现在我们希望自定义登录页面(默认的登录页面很丑),但是身份校验还是希望由security来进行。这时候我们只需要将登录页面重定向到我们自定义页面即可,这时候DIY表单,但是在这里切记一点。登录页面重定向的地址和表单提交的地址务必一致! - 自定义配置 AuthConfig.java
在原来的基础上扩展了DIY登录页面的控制器的设置
package com.hjl.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* 自定义身份验证类(用于重写WebSecurityConfigurerAdapter默认配置)
* @Configuration 表示这是一个配置类
* @EnableWebSecurity 允许security
* configure() 该方法重写了父类的方法,用于添加用户与角色
* */
@Configuration
@EnableWebSecurity
public class AuthConfig extends WebSecurityConfigurerAdapter{
/**
* 重写该方法,添加自定义用户
* */
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
//inMemoryAuthentication 从内存中获取
//密码进行加密
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("admin")).roles("ADMIN","USER")
.and()
.withUser("user").password(new BCryptPasswordEncoder().encode("user")).roles("USER");
}
/**
* 重写该方法,设定用户访问权限
* 用户身份可以访问 订单相关API
* */
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN") // 管理员权限
.antMatchers("/user/**").hasRole("USER") //用户权限
.and()
.formLogin()
.loginPage("/login") //跳转登录页面的控制器,该地址要保证和表单提交登录页面的地址一致!(如:通过/login访问的登录页面 这里也是/login )
.permitAll()
.and()
.logout()
.permitAll()
.and()
.csrf().disable(); //暂时禁用CSRF,否则无法提交表单
}
}
- 添加 login(get方式)控制器
即如果用户没有登录就访问受保护的资源,系统将会进行拦截,拦截之后会请求/login(get方式),然后经过我们这个控制器跳转到DIY登录页面。
在TestController.java中添加访问login.html的方法
@RequestMapping(value="/login")
public String test() {
return "login";
}
- 登录页面 (login.html) 注意:这里表单的action为 /login 提交方式为POST
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<h2>自定义登录页面</h2>
<hr>
<form action="/login" method="POST" name="f">
用户名<input type="text" name="username"/> <br>
密码 <input type="password" name="password"> <br>
<input type="submit" value="登录">
</form>
</body>
</html>
访问:http://localhost:8080/admin 跳转到login.html页面
输入admin用户密码,成功跳转页面