1. 程式人生 > >Spring Boot中使用Spring Security自定義驗證

Spring Boot中使用Spring Security自定義驗證

因為網上關於這個springboot+security自定義驗證有好多寫的有點雜亂,在仿寫的過程中總是出現莫名其妙的bug,所以專門寫一篇最基礎的出來。

本篇還是使用熟悉的springboot+mybatis+thymeleaf來搭最基礎的架構,當然不用資料庫也是可以的,自己在邏輯實現類新建一個物件測試就好了。

一、新建資料庫
這裡寫圖片描述

二、開啟IDEA新建專案,勾這三個

這裡寫圖片描述

這裡寫圖片描述

三、專案架構

這裡寫圖片描述

四、各部分的實現

1、pom.xml下新增mybatis和mysql的依賴,以及對xml路徑的支援

<!--mybatis-->
        <dependency
>
<groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!--mysql--> <dependency> <groupId>
mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency>
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId
>
<artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build>

2、application.properties檔案下新增資料庫的資訊

spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
mybatis.mapperLocation=classpath*:com/**/*Mapper.xml

3、持久層mapper包下

建立UserMapper介面

package com.mapper;

import com.model.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * Created by Administrator on 2016/12/9.
 */
@Mapper
public interface UserMapper {
    User selectById(String id);
    User selectByUsername(String username);
}

同包下建立UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mapper.UserMapper" >
  <resultMap id="BaseResultMap" type="com.model.User" >
    <id column="id" property="id" jdbcType="VARCHAR" />
    <result column="username" property="username" jdbcType="VARCHAR" />
    <result column="password" property="password" jdbcType="VARCHAR" />
    <result column="role" property="role" jdbcType="VARCHAR" />
  </resultMap>

  <select id="selectById" resultMap="BaseResultMap" >
    select id, username,password,role
    from user
    where id = #{id, jdbcType=VARCHAR}
  </select>
  <select id="selectByUsername" resultMap="BaseResultMap" >
    select id, username,password,role
    from user
    where username = #{username, jdbcType=VARCHAR}
  </select>

</mapper>

4、實體層model建立實體類User,繼承UserDetails

package com.model;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;

/**
 * Created by Administrator on 2016/12/9.
 */
public class User implements Serializable, UserDetails  {
    private String id;
    private String username;
    private String password;
    private String role;

    public User(){}

    public User(String username, String password, String  role){

        this.setUsername(username);
        this.setPassword(password);
        this.setRole(role);

    }
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority(getRole()));
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

5、安全層security包下建立SecurityConfig類,處理登入許可權等等。

package com.security;

import com.service.UserService;
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;

@Configuration
//@EnableWebSecurity: 禁用Boot的預設Security配置,配合@Configuration啟用自定義配置
// (需要擴充套件WebSecurityConfigurerAdapter)
@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true): 啟用Security註解,
// 例如最常用的@PreAuthorize
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        // Configure spring security's authenticationManager with custom
        // user details service
        auth.userDetailsService(this.userService);
    }

    @Override
    //configure(HttpSecurity): Request層面的配置,對應XML Configuration中的<http>元素
    //定義URL路徑應該受到保護,哪些不應該
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                // 例如以下程式碼指定了/和/index不需要任何認證就可以訪問,其他的路徑都必須通過身份驗證。
                .antMatchers("/", "/index").permitAll()
                .anyRequest().authenticated()
                .and()
                //通過formLogin()定義當需要使用者登入時候,轉到的登入頁面。
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                //登出
                .logout()
                .permitAll();
        //關閉csrf 防止迴圈定向
        http.csrf().disable();
    }


}

6、業務邏輯層service建立UserService類

package com.service;

import com.mapper.UserMapper;
import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 * Created by Administrator on 2016/12/13.
 */
@Service
public class UserService implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.selectByUsername(username);

        if( user == null ){
            throw new UsernameNotFoundException(String.format("User with username=%s was not found", username));
        }

        return user;
    }
}

7、網路層(我比較喜歡叫控制層)controller下建立HelloController類
這裡對映到resources目錄下的templates的html頁面。

package com.controller;

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

@Controller
public class HelloController {

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

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

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

}

8、在resources目錄下的templates建立3個html(預設頁,登入頁跟登入後才能進入的頁面)

hello.xml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
    <input type="submit" value="登出"/>
</form>
</body>
</html>

index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
    <input type="submit" value="登出"/>
</form>
</body>
</html>

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
    <input type="submit" value="登出"/>
</form>
</body>
</html>

五、做完以上,就能實現最基礎的web安全控制了,當然你還可以加url的許可權控制,這些網上可搜到很多資料而且不會亂。我這裡展示一下。

1、資料庫中加入測試資料

這裡寫圖片描述

這裡要注意的是role必須為ROLE_xx形式,不然security識別不出來。

2、在controller類中加入以下控制方法

@RequestMapping(value = "/helloadmin")
    //對應資料庫中role為“ROLE_admin”
    @PreAuthorize("hasAnyRole('admin')")
    public String helloAdmin(){
        return "helloadmin";
    }

    @RequestMapping(value = "/hellouser")
    //對應資料庫中role為“ROLE_admin”與“ROLE_user”
    @PreAuthorize("hasAnyRole('admin', 'user')")
    public String helloUser(){
        return "hellouser";
    }

3、然後你自己新增倆個測試html(hellouser.html與helloadmin.html),發現以使用者名稱為user登入是進不去helloadmin的。

這裡寫圖片描述

相關推薦

Spring Boot使用Spring Security定義驗證

因為網上關於這個springboot+security自定義驗證有好多寫的有點雜亂,在仿寫的過程中總是出現莫名其妙的bug,所以專門寫一篇最基礎的出來。 本篇還是使用熟悉的springboot+mybatis+thymeleaf來搭最基礎的架構,當然不用資

Spring Boot Shiro許可權管理--定義 FormAuthenticationFilter驗證碼整合

驗證碼 思路 shiro使用FormAuthenticationFilter進行表單認證,驗證校驗的功能應該加在FormAuthenticationFilter中,在認證之前進行驗證碼校驗。 需要寫FormAuthenticationFilter的子類,繼承FormAuth

Spring Boot Admin 集成定義監控告警

doctype etc exce err art bstr tst notifier ESS Spring Boot Admin 集成自定義監控告警 前言 Spring Boot Admin 是一個社區項目,可以用來監控和管理 Spring Boot 應用並且提供 UI,詳

Spring boot 學習筆記 1 - 定義錯誤

note ride 覆蓋 ide rac med exception cat 異常 Spring Boot提供了WebExceptionHandler一個以合理的方式處理所有錯誤的方法。它在處理順序中的位置就在WebFlux提供的處理程序之前,這被認為是最後一個處理程序。

Spring Boot-錯誤處理及定義全域性異常處理機制

正常的Web應用開發時,需要考慮到應用執行發生異常時或出現錯誤時如何來被處理,例如捕獲必要的異常資訊,記錄日誌方便日後排錯,友好的使用者響應輸出等等。 當然應用發生錯誤,有可能是應用自身的問題,也有可能是客戶端操作的問題。 Spring Boot預設提供了一種錯誤處理機制。 預設錯誤處理機制

spring boot整合swagger,定義註解,攔截器,xss過濾,非同步呼叫,定時任務案例

本文介紹spring boot整合swagger,自定義註解,攔截器,xss過濾,非同步呼叫,定時任務案例 整合swagger--對於做前後端分離的專案,後端只需要提供介面訪問,swagger提供了介面呼叫測試和各種註釋的視覺化web介面。配置swagger的掃描包路徑,api資訊等,見配置類Swagger

Spring Boot 常用配置以及定義配置

原文地址:https://renguangli.com/articles/spring-boot-config Spring Boot 常用配置簡單介紹及使用 多環境配置 Spring Boot Profile 在 Spring Boot 中多環境配置檔名需要滿足 app

Spring Boot系列——AOP配定義註解的最佳實踐

AOP(Aspect Oriented Programming),即面向切面程式設計,是Spring框架的大殺器之一。 首先,我宣告下,我不是來系統介紹什麼是AOP,更不是照本宣科講解什麼是連線點、切面、通知和切入點這些讓人頭皮發麻的概念。 今天就來說說AOP的一些應用場景以及如何通過和其他特性的結合提升

spring boot 掃描不到定義的Controller。。。

    springboot專案的特色,這裡就不多說了,框架搭建是非常簡單的;小編在搭建成功之後遇到了如下問題:     掃描不到自定義的controller。。。     文章介紹兩個可能的問題方案: &nbs

spring bootspring security實現單點登入,傳統模式(一)

單點登入是什麼? 一個系統中可能會引用別的很多系統。單點登入就是解決,一次登入,就可以訪問所有的系統。 每次瀏覽器向一個域名傳送http請求,會去查詢域名的cookie資訊拼接到http的header中傳送到伺服器。 cookie不能跨域。這個域是瀏覽器請求的域名,哪怕他們都是訪問一

spring boot系統登入實現定義攔截器

在專案中,我們會對使用者請求的url統一處理,此處如果我們不用其他的管理框架,我們可以自定義攔截器,通過控制使用者的請求路徑進而控制使用者的訪問限制 自定義攔截器 /** * 登入攔截器 * @author kexin * @date 2018/11/09 */ public

Spring cloud的服務定義路由

很多情況下我們需要服務自定義路由,比如需要灰度釋出時線上驗證環境、生產環境的服務例項路由是需要區分的,還有在SAAS化應用中,經常會把租戶分成一個個組,每組分配幾個服務例項,就是說組內服務例項共享,組間是隔離的。   本文在Spring Cloud的基礎上,給出了一個服務分

spring boot spring security使用資料庫儲存許可權

WebSecurityConfig package com.maven; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowire

使用Spring Boot的AOP處理定義註解

前言 上一篇文章Java 註解介紹講解了下Java註解的基本使用方式,並且通過自定義註解實現了一個簡單的測試工具;本篇文章將介紹如何使用Spring Boot的AOP來簡化處理自定義註解,並將通過實現一個簡單的方法執行時間統計工具為樣例來講解這些內容。

Spring Boot學習之路——定義攔截器

Spring Boot簡介 Spring Boot很大程度上簡化了基於Spring的應用開發,只需要呼叫“run”方法就可以建立一個獨立的,產品級別的Spring應用。Spring Boot能夠為所有Spring開發提供一個從根本上更快,且隨處可得的入門體驗;

spring boot全域性異常的定義

全域性異常 import com.alibaba.fastjson.JSON; import com.ziku.msp.common_enum.ErrorCodeEnum; import com.ziku.msp.exception.BizException; import

spring boot(三)定義啟動器 swagger2

開發十年,就只剩下這套架構體系了! >>>   

spring boot Spring data jpa數據庫表字段命名策略

_id -s ber data 駝峰命名 org body strategy 命名 spring boot 中Spring data jpa命名策略 數據庫,表字段命名是駝峰命名法(UserID),Spring data jpa 自動更新之後是 user_id, 表字段不對

spring-bootspring.jackson.date-format失效及解決辦法

spring-boot 版本 <parent> <groupId>org.sp

Spring Boot整合Spring Security定義驗證程式碼

最終效果 1、實現頁面訪問許可權限制 2、使用者角色區分,並按照角色區分頁面許可權 3、實現在資料庫中儲存使用者資訊以及角色資訊 4、自定義驗證程式碼 效果如下: 1、免驗證頁面 2、登陸頁面 在使用者未登入時,訪問任意有