SpringBoot坚持学习第十天:集成SpringSecurity

版权声明:欢迎转载大宇的博客,转载请注明出处: https://blog.csdn.net/yanluandai1985/article/details/86147801

一、搭建基本页面

        导入页面的依赖并且关闭页面的缓存。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
spring.thymeleaf.cache=false

         编写一个index的页面。 

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>index</title>
</head>
<body>
<h1>Hello SpringBoot</h1>
</body>
</html>
    @RequestMapping("/")
    public String index() {
        return "index";
    }

核心:引入SpringSecurity,导入SpringSecurity的stater。

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

        再次启动项目发现启动日志上出现了

        启动项目后再次访问http://localhost:8080/,跳转到了SpringSecurity默认的登录页面。

        用户名默认为user,密码在控制台上打开。

        可以连续按两次shift,找到UserDetailsServiceAutoConfiguration这个类的源码。可找到打印的这行代码,进行相关的源码分析。

        如果想修改用户名和密码,可以在 application.properties 重新进行配置

# security
spring.security.user.name=admin
spring.security.user.password=admin

二、认证与退出

        首先把我踩过的坑先提炼出来

(1)两个请求的请求名称相同,但是请求方式不一样,一个是GET,另外一个是POST,那么进入的后台方法就不同。

(2)SpringSecurity的 登录请求/login  与 登出请求/logout 只支持POST方法。

       好了,先编写一个项目的根目录,项目的根目录可以跳转一个主页。但是主页是要求登录后才能查看。所以在跳转主页的过程中,请求会被重定向到登录认证页面。如果认证成功,则跳转主页,反之则提示用户登录失败。

        最先编写跳转index.html的代码。

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

  编写index.html页面。主页中使用 thymeleaf 模版引擎,发送进入  受限制页面 /home 请求。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>index</title>
</head>
<body>
<h1>Hello SpringBoot</h1>
<a th:href="@{/home}">进入主页</a>
</body>
</html>

        请求将会被SpringSecurity拦截。就像Shiro的拦截器那样。

        在下面的配置中

        "/" 与 "/index" 这两个请求是不需要认证的。

        anyRequest().authenticated()表明其它请求都需要认证拦截。好比Shiro中的 auth拦截器。

        然后接着配置:认证路径,配置好认证路径是/login,这个请求注意了,是GET处理方式,需要与SpringSecurity提供的POST方式区别开来。所以,我们要在Controller中编写一个处理/login请求并且是GET方式的代码。此外,登录认证请求是不需要被拦截的。

        最后配置退出请求,配制成 /logout,表示为退出资源。在页面中使用POST方式的,将被发送到SpringSecurity中处理它。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //这两个请求不需要认证,相当于Shiro中的 anon拦截器
                .antMatchers("/", "/index").permitAll()
                //其余任何请求需要先登录验证,否则跳转到登录页面
                .anyRequest().authenticated()
                //配置登录页面
                .and()
                .formLogin()
                //注释掉下面的自定义登录请求,就会跳转到springsecurity的默认登录页
                .loginPage("/login")
                .permitAll()
                //退出请求不拦截,退出请求默认是/logout
                .and()
                .logout()
                .permitAll()
                //忽略退出请求的同源限制
                .and()
                .csrf()
                .ignoringAntMatchers("/logout");
    }
}

好了,在index页面中发送/home请求,将会被重定向到/login GET 请求。这个在上述配置中的loginPage("/login") 配置好了。我们来编写处理 /login  GET 请求的处理程序。此请求最终重定向到login.html中。

    /**
     * 此处必须指明为GET方法
     * 与SpringSecurity中的/login区别开来
     *
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login() {
        return "login";
    }

编写login.html。在页面上配置好一个form表单,发送路径依旧为 /login ,但是处理方式是POST,这个请求将会被发送到SpringSecurity中处理。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<div th:if="${param.error}">
    用户名或密码错
</div>
<div th:if="${param.logout}">
    您已注销成功
</div>
<!-- 使用thymeleaf模版引擎 ,需要指明为post请求-->
<form th:action="@{/login}" method="post">
    用户名<input type="text" name="username"><br>
    密码<input type="password" name="password"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

        如果登录成功,将会跳转到/home。默认的帐号密码可以在配置文件中配置。

# security
spring.security.user.name=admin
spring.security.user.password=admin

最后编写处理/home请求的代码。这个请求将会跳转到home.html中。

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

 在home页面中,再配置一个退出请求。退出请求使用POST方式,发送给SpringSecurity处理。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>核心业务页面</title>
</head>
<body>
<h3>核心业务页面,需要登录</h3>
<form method="post" th:action="@{/logout}">
   <button type="submit">退出</button>
</form>
</body>
</html>

三、角色与权限

指明帐号密码对应的权限

访问 "/admin/**"需要ADMIN角色

访问"/home/**"需要ADMIN与USER角色

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //指明"/resource/**"请求与"/"请求可以直接访问
                .antMatchers("/resources/**", "/").permitAll()
                //指明"/admin/**"请求需要ADMIN角色
                .antMatchers("/admin/**").hasRole("ADMIN")
                //指明"/home/**"需要ADMIN或者USER角色
                .antMatchers("/home/**").access("hasRole('ADMIN') or hasRole('USER')")
                //其它任何请求需要先登录
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and()
                .csrf()
                .ignoringAntMatchers("/logout");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        ...
    }
}

再为用户配置角色与权限信息

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                //指明加密方式
                .passwordEncoder(new BCryptPasswordEncoder())
                //优先使用Java中的配置
                .withUser("user")
                .password(new BCryptPasswordEncoder()
                        //指明角色为USER
                        .encode("123456")).roles("USER")
                .and()
                .withUser("admin")
                .password(new BCryptPasswordEncoder()
                        //指明角色为ADMIN与USER
                        .encode("admin")).roles("ADMIN", "USER");
    }
    @RequestMapping("/admin")
    public String admin() {
        return "admin";
    }

最后编写 admin.html。退出使用POST方式 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>admin页面</title>
</head>
<body>
<h3>管理员页面admin</h3>
<form method="post" th:action="@{/logout}">
    <button type="submit">退出</button>
</form>

</form>
</body>
</html>

 

四、附录

        更多的权限控制方式参看下表:

方法名 解释
access(String) Spring EL 表达式结果为 true 时可访问
anonymous() 匿名可访问
denyAll() 用户不可以访问
fullyAuthenticated() 用户完全认证可访问(非 remember me 下自动登录)
hasAnyAuthority(String...) 参数中任意权限的用户可访问
hasAnyRole(String...) 参数中任意角色的用户可访问
hasAuthority(String) 某一权限的用户可访问
hasRole(String) 某一角色的用户可访问
permitAll() 所有用户可访问
rememberMe() 允许通过 remember me 登录的用户访问
authenticated() 用户登录后可访问
hasIpAddress(String) 用户来自参数中的 IP 时可访问

猜你喜欢

转载自blog.csdn.net/yanluandai1985/article/details/86147801