探索Spring

Spring Security介绍

2019-10-13  本文已影响0人  Real_man

Spring Security是Spring提供的一个安全框架,提供认证和授权功能,最主要的是它提供了简单的使用方式,同时又有很高的灵活性,简单,灵活,强大。

基础

SecurityContextHolder,SecurityContext,Authentication是Spring Security的基础对象。

在应用中获取当前用户信息:

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (principal instanceof UserDetails) {
    String username = ((UserDetails)principal).getUsername();
} else {
    String username = principal.toString();
}

案例

1 Spring Boot项目中引入Spring Security的依赖包

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2 配置SpringSecurity的安全信息

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // @formatter:off
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/css/**", "/index").permitAll()
                    
                    // 只有USER权限的角色才能访问/user/接口
                    .antMatchers("/user/**").hasRole("USER")
                    .and()
                .formLogin().loginPage("/login").failureUrl("/login-error");
    }

//  @Autowired
//  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//      auth
//          .inMemoryAuthentication()
//              .withUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER"));
//  }
    // @formatter:on

    // 密码明文
    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder encoder = NoOpPasswordEncoder.getInstance();
        return encoder;
    }


  // 获取用户的来源
    @Bean
    public UserDetailsService userDetailsService(){
        UserDetailsService userDetailsService = new UserDetailsService(){

            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                if (StringUtils.isEmpty(username) || !"admin".equalsIgnoreCase(username)){
                    return null;
                }

                HashSet<GrantedAuthority> hashSet = new HashSet<>();
                // 内部检验权限,要以ROLE为前缀
                hashSet.add(new  SimpleGrantedAuthority("ROLE_USER") );
                User user = new User("admin","test",hashSet);

                return user;
            }
        };
        return userDetailsService;
    }
}

3 编写接口类

@Controller
public class MainController {

    @RequestMapping("/")
    public String root() {
        return "redirect:/index";
    }

    @ResponseBody
    @RequestMapping("/index")
    public String index() {
        return "当前为未经安全认证的页面";
    }

    @ResponseBody
    @RequestMapping("/user/index")
    public String userIndex() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        
        return "user/index";
    }

    @RequestMapping("/login")
    public String login() {
        return "login";
    }

    @ResponseBody
    @RequestMapping("/login-error")
    public String loginError(Model model) {
//      model.addAttribute("loginError", true);
        return "login-error";
    }

}

4 登录页面

// 位置 src/main/resources/templates/login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
    <head>
        <title>Login page</title>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
    </head>
    <body>
        <h1>Login page</h1>
        <p>Example user: user / password</p>
        <p th:if="${loginError}" class="error">Wrong user or password</p>
        <form th:action="@{/login}" method="post">
            <label for="username">Username</label>:
            <input type="text" id="username" name="username" autofocus="autofocus" /> <br />
            <label for="password">Password</label>:
            <input type="password" id="password" name="password" /> <br />
            <input type="submit" value="Log in" />
        </form>
        <p><a href="/index" th:href="@{/index}">Back to home page</a></p>
    </body>
</html>

5 效果。

6 如果想要测试授权功能,在userDetailsService中返回结果去掉ROLE_USER权限即可。

调试关键点

org.springframework.security.access.vote.AffirmativeBased#decide 判断用户是否有权访问当前接口

org.springframework.security.authentication.dao.DaoAuthenticationProvider#additionalAuthenticationChecks 密码加密校验

最后

本文简单介绍了Spring Security的基础内容,给了一个简单的案例,自行运行查看效果

上一篇 下一篇

猜你喜欢

热点阅读