1. 程式人生 > >在Spring Boot中整合Spring Security並自定義驗證程式碼

在Spring Boot中整合Spring Security並自定義驗證程式碼

最終效果

1、實現頁面訪問許可權限制
2、使用者角色區分,並按照角色區分頁面許可權
3、實現在資料庫中儲存使用者資訊以及角色資訊
4、自定義驗證程式碼

效果如下:
1、免驗證頁面
這裡寫圖片描述
2、登陸頁面
在使用者未登入時,訪問任意有許可權要求的頁面都會自動跳轉到登陸頁面。
這裡寫圖片描述
3、需登陸才能檢視的頁面
使用者登陸後,可以正常訪問頁面資源,同時可以正確顯示使用者登入名:
這裡寫圖片描述
4、使用者有角色區分,可以指定部分頁面只允許有相應使用者角色的人使用
4.1、只有ADMIN覺得使用者才能檢視的頁面(許可權不足)
這裡寫圖片描述
4.2、只有ADMIN覺得使用者才能檢視的頁面(許可權滿足)
這裡寫圖片描述

以下具體說明實現步驟。

程式碼實現

MAVEN引入依賴

在pom.xml中引入spring security依賴

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

配置Spring Security

在Spring中,配置和使用Spring Security,在不需要修改太多流程細節的情況下僅需宣告好攔截規則,同時自定義驗證過程中的主要實現介面(使用者資訊UserDetails,使用者資訊獲取服務UserDetailsService,驗證工具AuthenticationProvider)即可。其餘的流程將由Spring自動接管,非常方便。

啟動配置

在專案包下新增WebSecurityConfigurerAdapter 的具體實現類,實現Spring Security的啟動配置
程式碼如下:

@Configurable
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//允許進入頁面方法前檢驗
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAuthenticationProvider provider;//自定義驗證
@Autowired private UserDetailsService userDetailsService;//自定義使用者服務 @Autowired public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception{ } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(StaticParams.PATHREGX.NOAUTH, StaticParams.PATHREGX.CSS,StaticParams.PATHREGX.JS,StaticParams.PATHREGX.IMG).permitAll()//無需訪問許可權 .antMatchers(StaticParams.PATHREGX.AUTHADMIN).hasAuthority(StaticParams.USERROLE.ROLE_ADMIN)//admin角色訪問許可權 .antMatchers(StaticParams.PATHREGX.AUTHUSER).hasAuthority(StaticParams.USERROLE.ROLE_USER)//user角色訪問許可權 .anyRequest()//all others request authentication .authenticated() .and() .formLogin().loginPage("/login").permitAll() .and() .logout().permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //將驗證過程交給自定義驗證工具 auth.authenticationProvider(provider); }

URL攔截配置

URL攔截配置可以在上一小節的WebSecurityConfig 中配置,但是此方法適用於大方向上的配置,具體的特殊路徑也可以在@Controller的註解中具體配置。詳細說明可以參考:Spring Boot Security Application

如下:

    @ResponseBody
    @PreAuthorize("hasAuthority('"+StaticParams.USERROLE.ROLE_ADMIN+"')")//這裡可以指定特定角色的使用者訪問許可權
    @RequestMapping(value = "adminrequire", method = RequestMethod.GET)
    public String adminrequire(){
        return "HELLO from web but you should be admin";
    }

使用者、角色表

在本文例子中使用者和角色可以有一對多的關係因此可以將使用者和角色分成兩張表。有些例子將使用者和許可權寫在同一張表上也是可以的。

/*使用者表*/
@Entity
@Table(name = "user")
public class SystemUser {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String userName;
    private String password;

    public SystemUser(){}

    public SystemUser(SystemUser user){
        this.userName = user.getUserName();
        this.password = user.getPassword();
        this.id = user.getId();
    }

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
/*角色表*/
@Entity
@Table(name = "user_role")
public class UserRole {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String role;
    private Long userId;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
}

自定義驗證

在Spring Boot的Spring Security的教程中預設的使用者名稱、密碼、許可權是在程式碼中指定的

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }

這顯然是不符合應用需求的,所以我們需要提供自定義的AuthenticationProvider,並在上邊程式碼中替換即可。在此之前,我們應該重寫獲取使用者User和許可權的方法。通過查詢相關資料和API,方法提供如下:

自定義UserDetails

UserDetails代表了Spring Security的使用者認證實體,帶有使用者名稱、密碼、許可權列表、過期特性等性質,可以自己宣告類實現UserDetails介面,如果不想自己宣告,也可以用SpringSecurity的預設實現org.springframework.security.core.userdetails.User 本文例子中採用自定義類:

public class MyUserDetails extends SystemUser implements UserDetails{

    private List<UserRole> roles;

    public MyUserDetails(SystemUser user, List<UserRole> roles){
        super(user);
        this.roles = roles;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if(roles == null || roles.size() <1){
            return AuthorityUtils.commaSeparatedStringToAuthorityList("");
        }
        StringBuilder commaBuilder = new StringBuilder();
        for(UserRole role : roles){
            commaBuilder.append(role.getRole()).append(",");
        }
        String authorities = commaBuilder.substring(0,commaBuilder.length()-1);
        return AuthorityUtils.commaSeparatedStringToAuthorityList(authorities);
    }

    @Override
    public String getPassword() {
        return super.getPassword();
    }

    @Override
    public String getUsername() {
        return super.getUserName();
    }

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

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

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

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

}

自定義UserDetailsService

UserDetailsService提供了獲取UserDetails的方式,只要實現UserDetailsService介面即可,最終生成使用者和許可權共同組成的UserDetails,在這裡就可以實現從自定義的資料來源中獲取使用者資訊了:

@Service("MyUserDetailsImpl")
public class MyUserDetailsService implements UserDetailsService {
    @Resource(name = "SystemUserServiceImpl")
    private SystemUserService systemUserService;

    @Resource(name = "UserRoleServiceImpl")
    private UserRoleService userRoleService;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        SystemUser user;
        try {
            user = systemUserService.findByName(userName);
        } catch (Exception e) {
            throw new UsernameNotFoundException("user select fail");
        }
        if(user == null){
            throw new UsernameNotFoundException("no user found");
        } else {
            try {
                List<UserRole> roles = userRoleService.getRoleByUser(user);
                return new MyUserDetails(user, roles);
            } catch (Exception e) {
                throw new UsernameNotFoundException("user role select fail");
            }
        }
    }
}

自定義AuthenticationProvider

AuthenticationProvider 提供使用者UserDetails的具體驗證方式,在這裡可以自定義使用者密碼的加密、驗證方式等等。因為博文主要講的是如何引入Spring Security和如何自定義驗證程式碼,所以這裡為了簡便,我直接採用明文比較方式:

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private MyUserDetailsService userService;

    /**
     * 自定義驗證方式
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();
        MyUserDetails user = (MyUserDetails) userService.loadUserByUsername(username);
        if(user == null){
            throw new BadCredentialsException("Username not found.");
        }

        //加密過程在這裡體現
        if (!password.equals(user.getPassword())) {
            throw new BadCredentialsException("Wrong password.");
        }

        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
        return new UsernamePasswordAuthenticationToken(user, password, authorities);
    }

    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }

}

相關推薦

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

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

Spring Boot使用Spring Security定義驗證

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

企業分布式微服務雲SpringCloud SpringBoot mybatis (六)Spring Boot使用Spring Security進行安全控制

spring ron public 控制 應用 app ebs cloud 來源 準備工作 首先,構建一個簡單的Web工程,以用於後續添加安全控制,也可以用之前Chapter3-1-2做為基礎工程。若對如何使用Spring Boot構建Web應用,可以先閱讀《Spring

Spring Boot使用Spring Security實現權限控制

unicode then add sta spa 攔截器 nco throw views Spring Boot框架我們前面已經介紹了很多了,相信看了前面的博客的小夥伴對Spring Boot應該有一個大致的了解了吧,如果有小夥伴對Spring Boot尚不熟悉

SpringBoot2.0學習筆記:(十) Spring Boot整合Redis

一、關於Lettuce 關於在SpringBoot2.0.x版本中整合Redis,我們先看一下官方的遷移文件有什麼說的: Spring Boot2.0遷移指南 當你使用spring-boot-starter-redis的時候,Lettuce現已取代Jedis作為Redis驅動

新手入門教程-------Spring Boot整合RabbitMQ

AMQP:是Advanced Message Queuing Protocol的簡稱,高階訊息佇列協議,是一個面向訊息中介軟體的開放式標準應用層協議。   定義了以下特性: 訊息方向 訊息佇列 訊息路由(包括:點到點和釋出-訂閱模式) 可靠性 安全

Spring Boot】--整合Spring Security

目錄 1、建立工程 2、在pom.xml新增spring security的依賴 3、自定義使用者認證邏輯 4、關於使用者物件UserDetails 5、密碼加密解密PasswordEncoder 6、自定義登入介面 7、自定義登入介面 8、自定義處理成功 9

SpringBoot2.0學習筆記:(九) Spring Boot整合Mybatis與Druid

一、專案的搭建 Druid對Spring boot做了很好的適配,所有的工作都只需要在配置檔案中完成。 具體的Druid在Spring Boot中的配置可以看:GitHub文件 首先看一下專案引入的jar包: <dependencies> &

十九、Spring boot整合mybatis-generator自動生成程式碼

(一)新增外掛 <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugi

Spring Boot使用Spring Security進行安全控制

一 點睛 我們在編寫Web應用時,經常需要對頁面做一些安全控制,比如:對於沒有訪問許可權的使用者需要轉到登入表單頁面。要實現訪問控制的方法多種多樣,可以通過Aop、攔截器實現,也可以通過框架實現(如:Apache Shiro、Spring Security)。 本篇將具體

Spring Boot使用Spring Security實現許可權控制

Spring Boot框架我們前面已經介紹了很多了,相信看了前面的部落格的小夥伴對Spring Boot應該有一個大致的瞭解了吧,如果有小夥伴對Spring Boot尚不熟悉,可以先移步這裡從SpringMVC到Spring Boot,老司機請略過。OK,那我們

Spring Boot整合使用wagger2

Spring Boot中整合使用Swagger2構建RESTful APIs 在之前建立的入門級SpringBoot專案新增swagger2生產介面文件 pom檔案中匯入swagger2的jar包 建立swagger2配置類 其實這個配置類,只要

Spring Boot整合Sharding-JDBC讀寫分離示例

在我《Spring Cloud微服務-全棧技術與案例解析》書中,第18章節分庫分表解決方案裡有對Sharding-JDBC的使用進行詳細的講解。 之前是通過XML方式來配置資料來源,讀寫分離策略,分庫分表策略等,之前有朋友也問過我,有沒有Spring Boot

RabbitMq在spring boot整合和應用

具體如果安裝rabbitmq在本例子中不涉及,主要講解在springboot中如果傳送和接收rabbitmq訊息。 1.新增依賴 <dependency> <groupId>org.springframewor

Spring Boot整合Spring Security

綜合概述 Spring Security 是 Spring 社群的一個頂級專案,也是 Spring Boot 官方推薦使用的安全框架。除了常規的認證(Authentication)和授權(Authorization)之外,Spring Security還提供了諸如ACLs,LDAP,JAAS,CAS等高階特

spring boot 學習心得 使用JpaRepository註解定義SQL查詢數據庫多表查詢

自定義 net http entity onetomany tom pri 查詢語句 重點 一. 首先在@Entity註解的類裏面要寫好外鍵關系. 這個 @ManyToOne 註解可以建立外鍵關系, 不要在自己傻傻的寫一個 private int grades_id;

Spring Boot使用Spring-data-jpa實現分頁查詢(轉)

分頁查詢 log def inpu database ext identity odin btn 在我們平時的工作中,查詢列表在我們的系統中基本隨處可見,那麽我們如何使用jpa進行多條件查詢以及查詢列表分頁呢?下面我將介紹兩種多條件查詢方式。 1、引入起步依賴

Spring Boot 學習系列(05)—定義檢視解析規則

此文已由作者易國強授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 自定義檢視解析 在預設情況下Spring Boot 的MVC框架使用的檢視解析ViewResolver類是ContentNegotiatingViewResolver,這個解析器比較智慧,它會根據你的請求型別(一

Spring Boot 學習系列(08)—定義servlet、filter及listener

此文已由作者易國強授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 傳統的filter及listener配置 在傳統的Java web專案中,servlet、filter和listener的配置很簡單,直接在web.xml中按順序配置好即可,程式啟動時,就會按照你配置的順序依次載入

Spring Boot 學習系列(09)—定義Bean的順序加載

rri 學習 內容安全 master sys const nco 單純 分享圖片 此文已由作者易國強授權網易雲社區發布。歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。Bean 的順序加載有些場景中,我們希望編寫的Bean能夠按照指定的順序進行加載。比如,有UserSer