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

一、搭建基本页面

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

<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 时可访问
posted @ 2022-07-17 12:15  小大宇  阅读(78)  评论(0编辑  收藏  举报