天天看點

使用SpringSecurity

前幾天寫了一個SpringBoot對攔截器的使用,在實際項目中,對一些情況需要做一些安全驗證,比如在沒有登入的情況下通路特定的頁面應該解釋的攔截處理。這一篇介紹使用SpringSecurity來做簡單的安全控制,由于SpringSecurity比較複雜,如果有不對的地方可以大家一起學習。

建立項目,前端頁面使用thymeleaf,加入security依賴,pom檔案如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.dalaoyang</groupId>
    <artifactId>springboot_security</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot_security</name>
    <description>springboot_security</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.15</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
           

配置檔案本文就是将之前整合thymeleaf的配置拿了過來,代碼如下:

##端口号
server.port=8888


##去除thymeleaf的html嚴格校驗
spring.thymeleaf.mode=LEGACYHTML5

#設定thymeleaf檔案路徑 預設為src/main/resources/templates
spring.freemarker.template-loader-path=classpath:/templates
#設定靜态檔案路徑,js,css等
spring.mvc.static-path-pattern=/static/**
# 是否開啟模闆緩存,預設true
# 建議在開發時關閉緩存,不然沒法看到實時頁面
spring.thymeleaf.cache=false
# 模闆編碼
spring.freemarker.charset=UTF-8
           

接下來是這篇文章重要的地方,建立一個SecurityConfig類,繼承WebSecurityConfigurerAdapter類,重寫configure(HttpSecurity httpSecurity)方法,其中/css/和/index的資源不需要驗證,直接可以請求,/user/的資源需要驗證,權限是USER,/admin/**的資源需要驗證,權限是ADMIN,登入位址是/login,登入失敗位址是/login_error,異常重定向到 /401,登出跳轉到/logout。

注入AuthenticationManagerBuilder,在記憶體中建立一個使用者dalaoyang,密碼123的使用者,權限是USER,代碼如下:

package com.dalaoyang.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @author dalaoyang
 * @Description
 * @project springboot_learn
 * @package com.dalaoyang.config
 * @email [email protected]
 * @date 2018/4/28
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // /css/**和/index的資源不需要驗證,直接可以請求
    // /user/**的資源需要驗證,權限是USER /admin/**的資源需要驗證,權限是ADMIN
    // 登入位址是/login 登入失敗位址是 /login_error
    // 異常重定向到 /401
    // 登出跳轉到 /logout
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception{
        httpSecurity
                .authorizeRequests()
                .antMatchers("/css/**","/index").permitAll()
                .antMatchers("/user/**").hasRole("USER")
                .antMatchers("/admin/**").hasRole("ADMIN")
                .and()
                .formLogin().loginPage("/login").failureUrl("/login_error")
                .and()
                .exceptionHandling().accessDeniedPage("/401");

        httpSecurity.logout().logoutSuccessUrl("/logout");
    }


    //記憶體中建立使用者,使用者名為dalaoyang,密碼123,權限是USER
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("dalaoyang").password("123").roles("USER");
    }
}

           

建立一個TestController負責跳轉,代碼如下:

package com.dalaoyang.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author dalaoyang
 * @Description
 * @project springboot_learn
 * @package com.dalaoyang.controller
 * @email [email protected]
 * @date 2018/4/28
 */
@Controller
public class TestController {

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

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

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

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

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

    @RequestMapping("/login_error")
    public String login_error(Model model){
        model.addAttribute("login_error", "使用者名或密碼錯誤");
        return "login";
    }

    @RequestMapping("/logout")
    public String logout(Model model){
        model.addAttribute("login_error", "登出成功");
        return "login";
    }

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

           

建立一個user/index.html,用于校驗USER權限,沒有登入的話不能直接通路,代碼如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>user/index</title>
</head>
<body>
user/index

<form th:action="@{/logout}" method="post">
    <input type="submit" value="登出"/>
</form>
</body>
</html>
           

建立一個admin/index.html,隻允許ADMIN權限通路,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>admin</title>
</head>
<body>
admin/index
</body>
</html>
           

401頁面,用于沒有權限跳轉:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>401</title>
</head>
<body>
401
</body>
</html>
           

index頁面,任何權限都能通路

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
index
</body>
</html>
           

login頁面,用于登入

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<h1>login</h1>
<form th:action="@{/login}" method="post">
    <span th:text="${login_error}"></span>
<br/>
    <input type="text" name="username">使用者名<br/>
<input type="password" name="password">密碼<br/>
    <input type="submit" value="登入">
</form>
</body>
</html>
           

到這裡就全部建立完成了,啟動項目,通路

http://localhost:8888/

,如圖,可以直接通路。

image

通路

http://localhost:8888/user

被攔截到

http://localhost:8888/login

,如圖

先輸入錯誤的密碼,如圖

然後輸入使用者名dalaoyang密碼123,點選登入結果如圖

http://localhost:8888/admin

,如圖,沒有權限

我們在回到

點選登出,如圖

源碼下載下傳 :

大老楊碼雲

個人網站:

https://dalaoyang.cn