Spring 引导和安全动态身份验证和授权
Spring Boot and Security Dynamic Authentication and Authorization
我打算使用 spring 引导和安全开发一个登录页面,管理员可以创建用户和角色,这样系统就可以有很多角色和用户...管理员也可以将角色分配给用户并将其也删除。
我已经使用了很好的示例来说明如何实现它但是在阅读了这么多文档和教程之后仍然有以下问题并且不知道什么是实现 spring 安全和启动 together.tried 继续前进的最佳实践调试模式,逐步了解幕后发生的事情。
我的假设是每个 http 请求应用程序都引用 WebSecurityConfig class 来检查访问权限,但令人惊讶的是它不是那样的,因为 below.seems 应用程序转到配置 class 开始时,每件事 populates.bootstrap 在后台做了这么多动作,这让我感到困惑,无法理解 class 之间的关系。
configureGlobal-->configure-->无论你写什么 URL 它都会转到 /login) -->controller(登录方法)--> 使用 user/pass 提交表单 - -> loadUserByUsername --> controller(欢迎方法)--> welcome.jsp
1-当应用程序 加载 时,configureGlobal 和 configure 到底做了什么?
2-AuthenticationManagerBuilder 的确切作用是什么?
3-spring 安全性如何知道在表单提交后将 user/pass 发送到 loadUserByUsername 方法?
4-loadUserByUsername return 用户对象到哪里?因为当方法到达末尾时,它会重定向到控制器欢迎方法,并在用户名和密码正确时将您发送到欢迎方法。
4-如何使用 grantedAuthorities 根据用户的角色将用户重定向到不同的页面?
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<title>Log in with your account</title>
<link href="${contextPath}/resources/css/bootstrap.min.css" rel="stylesheet">
<link href="${contextPath}/resources/css/common.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<form method="POST" action="${contextPath}/login" class="form-signin">
<h2 class="form-heading">Log in</h2>
<div class="form-group ${error != null ? 'has-error' : ''}">
<span>${message}</span>
<input name="username" type="text" class="form-control" placeholder="Username"
autofocus="true"/>
<input name="password" type="password" class="form-control" placeholder="Password"/>
<span>${error}</span>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<button class="btn btn-lg btn-primary btn-block" type="submit">Log In</button>
<h4 class="text-center"><a href="${contextPath}/registration">Create an account</a></h4>
</div>
</form>
</div>
<!-- /container -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="${contextPath}/resources/js/bootstrap.min.js"></script>
</body>
</html>
WebSecurityConfig Class
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
UserDetailsServiceImpl class
@Service
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private UserRepository userRepository;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()){
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
}
}
用户控制器Class
@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private SecurityService securityService;
@Autowired
private UserValidator userValidator;
@RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute("userForm", new User());
return "registration";
}
@RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(@ModelAttribute("userForm") User userForm, BindingResult bindingResult, Model model) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.save(userForm);
securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/welcome";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("error", "Your username and password is invalid.");
if (logout != null)
model.addAttribute("message", "You have been logged out successfully.");
return "login";
}
@RequestMapping(value = {"/", "/welcome"}, method = RequestMethod.GET)
public String welcome(Model model) {
return "welcome";
}
}
我想分享一些我现在很清楚的问题的答案。
当你开始你的项目时,首先它会进入 WebSecurityConfig class 并寻找 configureGlobal 方法来构建身份验证过程,然后查找 configure 方法来设置安全性。
AuthenticationManagerBuilder 是一个 class 具有许多方法,例如 userDetailsService 用于基于用户详细信息,因此当您登录时,它会将凭据发送到已实现 UserDetailsService 接口的 class。
A POST 到 /login URL 将尝试对用户进行身份验证,因此 configureGlobal 将执行必要的操作。
它从 configureGlobal 方法调用并返回那里,仍然一切都在根路径中,因此将在控制器中找到正确的方法 class.
AuthenticationSuccessHandler 可以在这方面提供帮助。
我打算使用 spring 引导和安全开发一个登录页面,管理员可以创建用户和角色,这样系统就可以有很多角色和用户...管理员也可以将角色分配给用户并将其也删除。 我已经使用了很好的示例来说明如何实现它但是在阅读了这么多文档和教程之后仍然有以下问题并且不知道什么是实现 spring 安全和启动 together.tried 继续前进的最佳实践调试模式,逐步了解幕后发生的事情。
我的假设是每个 http 请求应用程序都引用 WebSecurityConfig class 来检查访问权限,但令人惊讶的是它不是那样的,因为 below.seems 应用程序转到配置 class 开始时,每件事 populates.bootstrap 在后台做了这么多动作,这让我感到困惑,无法理解 class 之间的关系。
configureGlobal-->configure-->无论你写什么 URL 它都会转到 /login) -->controller(登录方法)--> 使用 user/pass 提交表单 - -> loadUserByUsername --> controller(欢迎方法)--> welcome.jsp
1-当应用程序 加载 时,configureGlobal 和 configure 到底做了什么?
2-AuthenticationManagerBuilder 的确切作用是什么?
3-spring 安全性如何知道在表单提交后将 user/pass 发送到 loadUserByUsername 方法?
4-loadUserByUsername return 用户对象到哪里?因为当方法到达末尾时,它会重定向到控制器欢迎方法,并在用户名和密码正确时将您发送到欢迎方法。
4-如何使用 grantedAuthorities 根据用户的角色将用户重定向到不同的页面?
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<title>Log in with your account</title>
<link href="${contextPath}/resources/css/bootstrap.min.css" rel="stylesheet">
<link href="${contextPath}/resources/css/common.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<form method="POST" action="${contextPath}/login" class="form-signin">
<h2 class="form-heading">Log in</h2>
<div class="form-group ${error != null ? 'has-error' : ''}">
<span>${message}</span>
<input name="username" type="text" class="form-control" placeholder="Username"
autofocus="true"/>
<input name="password" type="password" class="form-control" placeholder="Password"/>
<span>${error}</span>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<button class="btn btn-lg btn-primary btn-block" type="submit">Log In</button>
<h4 class="text-center"><a href="${contextPath}/registration">Create an account</a></h4>
</div>
</form>
</div>
<!-- /container -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="${contextPath}/resources/js/bootstrap.min.js"></script>
</body>
</html>
WebSecurityConfig Class
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
UserDetailsServiceImpl class
@Service
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private UserRepository userRepository;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()){
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
}
}
用户控制器Class
@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private SecurityService securityService;
@Autowired
private UserValidator userValidator;
@RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute("userForm", new User());
return "registration";
}
@RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(@ModelAttribute("userForm") User userForm, BindingResult bindingResult, Model model) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.save(userForm);
securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/welcome";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("error", "Your username and password is invalid.");
if (logout != null)
model.addAttribute("message", "You have been logged out successfully.");
return "login";
}
@RequestMapping(value = {"/", "/welcome"}, method = RequestMethod.GET)
public String welcome(Model model) {
return "welcome";
}
}
我想分享一些我现在很清楚的问题的答案。
当你开始你的项目时,首先它会进入 WebSecurityConfig class 并寻找 configureGlobal 方法来构建身份验证过程,然后查找 configure 方法来设置安全性。
AuthenticationManagerBuilder 是一个 class 具有许多方法,例如 userDetailsService 用于基于用户详细信息,因此当您登录时,它会将凭据发送到已实现 UserDetailsService 接口的 class。
A POST 到 /login URL 将尝试对用户进行身份验证,因此 configureGlobal 将执行必要的操作。
它从 configureGlobal 方法调用并返回那里,仍然一切都在根路径中,因此将在控制器中找到正确的方法 class.
AuthenticationSuccessHandler 可以在这方面提供帮助。