springsecurity提供了基于用户、角色、权限的安全控制
简单使用
在项目中加入security的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
写一个接口
@RestController
public class IndexResource {
@RequestMapping({"", "/", "/index"})
public String index(){
return "index";
}
}
启动项目后,访问 localhost:8080 发现需要输入用户名密码。这其实是springsecurity的默认安全配置。
其实日志中已经有提示给我们:
2019-01-03 13:58:55.572 INFO 79013 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: de5cf28a-25d9-47d6-a0bd-bb4e41cf4d39
这段日志是从UserDetailsServiceAutoConfiguration
这个类中打印的。
private String getOrDeducePassword(User user, PasswordEncoder encoder) {
String password = user.getPassword();
if (user.isPasswordGenerated()) {
logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
}
return encoder == null && !PASSWORD_ALGORITHM_PATTERN.matcher(password).matches() ? "{noop}" + password : password;
}
密码有了,那用户名呢?
查看security的配置类org.springframework.boot.autoconfigure.security.SecurityProperties.User
,发现用户名默认为user,密码是临时UUID
public static class User {
private String name = "user";//用户名
private String password = UUID.randomUUID().toString();//密码
private List<String> roles = new ArrayList();
private boolean passwordGenerated = true;
public User() {
}
//...
}
然后在浏览器输入用户名密码,接口正常访问
自定义用户名密码配置
怎么自定义用户密码?
在配置文件中加入security的配置:
spring:
security:
user:
name: admin
password: admin
然后重新访问,输入admin / admin 访问成功。(部分浏览器需要清除之前的缓存才看到效果)
web页面安全访问
在web页面中一般都需要登录后(拿到session)才能访问
页面
先写2个页面
login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security 登录 </title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<form class="form-horizontal" th:action="@{/login}" method="post">
<h1>Login</h1>
<div th:if="${param.error}">
用户名或密码错
</div>
<div th:if="${param.logout}">
您已注销成功
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Username</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputEmail3" name="username" placeholder="Username">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3" name="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign in</button>
</div>
</div>
</form>
</body>
</html>
index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security入门</title>
</head>
<body>
<h1>欢迎使用Spring Security!</h1>
欢迎你:<p th:text="${username}"/></p>
<p>点击 <a th:href="@{/loginout}">这里</a> 退出登录</p>
</body>
</html>
当用户登录成功后跳转到index页面
安全配置
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* http访问控制
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/login").permitAll()//允许访问
.anyRequest().authenticated()//其他所有url都需要鉴权,如果未登陆则跳转登陆页面
.and()
.formLogin()
.loginPage("/login")//指定登录页面地
.loginProcessingUrl("/login")//登录处理url
.successForwardUrl("/home")//登录成功后跳转url
.permitAll()//允许访问
.and()
.logout().logoutUrl("/loginout").permitAll();//指定登出url,并且允许访问
}
/**
* 全局配置:
* 创建一个内存用户
* 用户名 admin
* 密码 admin
* 角色 USER
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//新版本security框架这里需要指定密码加密方式,不然报错:There is no PasswordEncoder mapped for the id “null”
BCryptPasswordEncoder pwdEncoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication()
.passwordEncoder(pwdEncoder)
.withUser("admin")
.password(pwdEncoder.encode("admin"))
.roles("ADMIN");
}
}
控制层
@RequestMapping("/login")
public String login(){
return "login";
}
@RequestMapping("/home")
public String home(Model model){
User principal = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
model.addAttribute("username", principal.getUsername());
return "index";
}
@RequestMapping("/loginout")
public String loginout(){
SecurityContextHolder.clearContext();
return "login";
}