在Spring Security&Thymeleaf中进行认证和授权

Spring Security 是什么

Spring Security是一个由Spring构建的框架,为应用程序提供身份验证和授权功能。只需添加一些配置,就可以使Web应用程序具有以下功能。

    • 脆弱性対策

セッションフィクセイション対策
クリックジャッキング対策
CSRF対策

認証・認可

フォーム認証などを用いたログイン機構
ロールを用いたアクセス制御

前提 tí) – prerequisite / premise / condition

這次要做的事

这次我们将使用Spring Security的功能来实现以下内容。

    • 認証

ユーザとパスワードを使ってフォーム認証する

(データベースでもできるが)インメモリに持たせたユーザとパスワードを使う
ユーザまたはパスワードが違っていたらエラーメッセージを返す

認可

管理者用アカウントと一般ユーザ用でロールを分ける

管理者は /admin と /user にアクセス可能
一般ユーザは /user のみにアクセス可能

请注意,以下将介绍启用 Spring Boot 应用程序安全的步骤。

图书馆的版本

请注意,使用Spring Boot 1.4系列和Spring Security 4.x系列。如果版本不同,则语法完全不同。

示例代码

我们在GitHub上发布了实际运行的示例代码。如果你想要通过阅读代码来理解,可以直接访问下方链接。

    https://github.com/gushernobindsme/spring-security-sample

前備份工作

添加依赖库

本次我们将使用Spring Boot构建服务器端,并使用Tymeleaf作为模板引擎进行页面绘制。为此,您需要以下库。

    • spring-boot-starter-web

 

    spring-boot-starter-thymeleaf

为了启用Spring Security的功能,需要以下库。

    • spring-boot-starter-security

 

    • spring-security-web

 

    spring-security-config

本次为了将Spring Security与Tymeleaf进行集成,我们需要添加以下库。

    thymeleaf-extras-springsecurity4

总结起来,build.gradle 文件将会添加如下配置。

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf:1.4.1.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-security:1.4.1.RELEASE")
    compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.3.RELEASE")
    compile("org.springframework.security:spring-security-core:4.2.3.RELEASE")
    compile("org.springframework.security:spring-security-web:4.2.3.RELEASE")
    compile("org.springframework.security:spring-security-config:4.2.3.RELEASE")
}

控制器

首先,我们将创建一个用于管理员的界面和一个用于一般用户的界面。
其中,管理员界面将命名为AdminController,而一般用户界面将命名为UserController。

@Controller
@RequestMapping("/admin")
@Slf4j
public class AdminController {

    @RequestMapping
    public String index() {
        return "admin";
    }
}
@Controller
@RequestMapping("/user")
@Slf4j
public class UserController {

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

}

模板

我們將為相應的Controller準備Tymeleaf模板。分別為admin.html和user.html(詳情請參考示例代碼)。

除此之外,按照 SpringBoot 的习惯创建 Application.java 文件,只要 gradle bootRun 能够通过,准备工作就完成了。

实施示例

由于做好了事前准备,我们现在转到Spring Security的讨论。

设置

首先,我们需要创建一个配置类来启用Spring Security。通过继承WebSecurityConfigurerAdapter并添加@EnableWebSecurity注解,我们就可以使Spring Security生效。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static String ROLE_USER = "USER";
    private static String ROLE_ADMIN = "ADMIN";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/user").hasAnyRole(ROLE_USER, ROLE_ADMIN)
                .antMatchers("/admin").hasRole(ROLE_ADMIN)
                .and()

                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/user")
                .usernameParameter("username")
                .passwordParameter("password")
                .permitAll()
                .and()

                .logout()
                .permitAll()
                .and()

                .csrf();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/*.html", "/*.css")
                .antMatchers("/bootstrap/**");
    }

}

对于上述例子,大致解释的是

#configure(HttpSecurity)

アクセス制御を有効にする

/user は一般ユーザと管理者ユーザのロールでアクセス可能とする

/admin は管理者ユーザのみアクセス可能とする

フォームログインを有効にする

ログインページの URL は /login とする

ユーザ名は username パスワードは password というプロパティ名とする

ログインに成功した場合は /user に遷移させる
ログインページに対しては、例外的にアクセス制御を無効にする

ログアウトページに対しては、例外的にアクセス制御を無効にする
CSRF 用のトークンを有効にする

#configure(WebSecurity)

デフォルト設定だと静的ファイルに対してもアクセス制御がかかってしまうため、以下については除外する

html
css
BootStrap テンプレートのファイル

差不多就是这样。我想你应该能够想象出设定的实施方式。

为了将Tymeleaf与SpringTemplateEngine配合使用,我们需要为TemplateResolver的实例设置SpringTemplateEngine。具体的实现如下所示。

@Autowired
public TemplateResolver templateResolver;

@Bean
public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.addDialect(new SpringSecurityDialect());
    engine.setTemplateResolver(templateResolver);
    return engine;
}

此外,还需要设置用于身份验证的用户名和密码信息。为了简化实现,本次设置将使用内存而非数据库。有关 UserDto 的示例代码,请参阅文档。

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    UserDto support = supportUser();
    UserDto admin = adminUser();

    auth.inMemoryAuthentication()
        .withUser(support.getUsername()).password(support.getPassword()).roles(ROLE_USER)
        .and()
        .withUser(admin.getUsername()).password(admin.getPassword()).roles(ROLE_ADMIN);
}

@Bean
@ConfigurationProperties("inmotion.admin")
public UserDto adminUser() {
    return new UserDto();
}

@Bean
@ConfigurationProperties("inmotion.user")
public UserDto supportUser() {
    return new UserDto();
}

我们决定将实际的用户名称和密码存储在 application.yml 中。

inmotion:
  user:
    username: user
    password: pass12345
  admin:
    username: admin
    password: pass12345

控制器

然后,准备与登录界面相对应的控制器。

@Controller
public class AuthenticationController {

    @RequestMapping({"/", "/login"})
    public String login(@RequestParam(value = "error", required = false) String error, Model model) {
        if (error != null) {
            // エラーメッセージを出力する処理
        }
        return "login";
    }

}

模板

只需准备一个登录表单来进行/login的POST即可。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <form class="form-signin" method="post" th:action="@{/login}">
        <div class="alert alert-dismissible alert-danger" th:if="${errorMessage}">
            <button type="button" class="close" data-dismiss="alert">×</button>
            <p th:text="${errorMessage}"></p>
        </div>
        <h2 class="form-signin-heading">Please sign in</h2>
        <label for="username" class="sr-only">Username</label>
        <input type="text" id="username" name="username" class="form-control" placeholder="UserName"/>
        <label for="password" class="sr-only">Password</label>
        <input type="password" id="password" name="password" class="form-control" placeholder="Password"/>
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
    </form>
</div>
</body>
</html>

使用Gradle bootRun命令启动应用程序

    • 指定したユーザ名、パスワードでログインできること

 

    • アクセス制御が有効になっていること

認可していない画面にアクセスしようとすると 403 が返ること

CSRF対策用のトークンが生成されていること

让我们来确认一下。

请参考相关资料。

    • Spring Security

 

    • Spring SecurityでWebの認証と認可を制御する – Developers.IO

 

    Spring Securityでユーザ認証を実装してみる – ももいろテクノロジー
广告
将在 10 秒后关闭
bannerAds