Spring Boot和安全动态身份验证和授权

时间:2017-08-25 14:27:55

标签: spring spring-mvc spring-boot spring-security spring-security-acl

我将使用spring boot和security开发一个登录页面,管理员可以创建用户和角色,这样系统可以拥有多个角色和用户......管理员也可以将角色分配给用户并删除它们。 我已经使用了很好的示例来实现它,但是在阅读了这么多文档和教程之后仍然有以下问题并且不知道实现spring安全性和启动的最佳实践是什么。试图继续调试模式以找出什么正在一步一步地发生在幕后。

我的假设是每个http请求应用程序引用WebSecurityConfig类来检查访问权限,但令人惊讶的是它不是那样的,而且那个人就像下面那样。应用程序在开始时进入配置类一次并且每个东西都填充.bootstrap在后台做了很多动作,这让我感到困惑,无法理解课程之间的关系。

configureGlobal - > configure - >无论你写什么URL到/登录) - >控制器(登录方法) - >用user / pass提交表单 - > loadUserByUsername - >控制器(欢迎方法) - >的welcome.jsp

1 - 当应用程序加载时,configureGlobal和configure的确切配置是什么?

2 - AuthenticationManagerBuilder的确切作用是什么?

3-spring security如何知道在将表单submition发送到loadUserByUsername方法后发送用户/ pass?

4-loadUserByUsername将用户对象返回到哪里?因为当方法到达结尾时,它会重定向到控制器欢迎方法,并在用户名和密码正确时将其发送给welcome方法。

4 - 如何使用授权权限根据用户的角色将用户重定向到不同的页面?

<%@ 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类

@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());
}
}

UserDetailsS​​erviceImpl类

@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);

}
}

UserController类

@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";
}


}

1 个答案:

答案 0 :(得分:0)

我想分享一些我现在清楚的问题的答案。

  1. 当您启动项目时,首先会转到 WebSecurityConfig 类并查找 configureGlobal 方法来构建身份验证过程,然后查找 configure 方法来设置安全性。

  2. AuthenticationManagerBuilder 是一个包含许多方法的类,例如 userDetailsS​​ervice ,用于根据用户详细信息进行身份验证,因此当您登录时,它会将凭证发送给类已实施 UserDetailsS​​ervice 界面。

  3. / login URL的POST将尝试对用户进行身份验证,以便configureGlobal完成所需的操作。

  4. 它已从 configureGlobal 方法调用并返回支持,但仍然所有内容都在根路径中,因此将在控制器类中找到正确的方法。

  5. AuthenticationSuccessHandler 可以在这方面提供帮助。