1. 程式人生 > >springboot學習之權限系統登錄驗證SpringSecurity

springboot學習之權限系統登錄驗證SpringSecurity

family 圖片 詳細信息 image details extends rri clas pro

SpringSecurity核心功能:認證、授權、攻擊防護(防止偽造身份)

涉及的依賴如下:

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

  



新建一個項目,添加如上依賴,在控制器controller中測試,指定url,比如
@Controller
public class UserController {

    @RequestMapping(value="/hello")
    @ResponseBody
    public String hello(){return "=======Welcome to HelloWorld==============";}
}

  

如上,原本啟動項目後,在地址欄中輸入http://localhost:8080/hello應該顯示返回的內容

然而此次加了安全驗證後,不管url中訪問的地址是什麽,hello還是hello111,均返回login頁面,如下

技術分享圖片

此時系統都沒有連DB,用戶名和密碼是什麽?

控制臺中有消息,比如Using generated security password: 76dade1c-f190-44f8-915c-7a6b6917fb9a【每次隨機生成的密碼】

將用戶名 user 和 密碼 76dade1c-f190-44f8-915c-7a6b6917fb9a 填入上面對話框中,點擊按鈕Sign in

技術分享圖片

若之前訪問的頁面是控制器中配置的頁面http://localhost:8080/hello

則此時能成功顯示

技術分享圖片

若之前範文的頁面是其他的,控制器中未配置的,則重定向後返回頁面不存在。

當前自己的項目中,總不能用系統生成的密碼進行登錄獲得權限,那不要被別人笑死。

進階階段:

我簡單創建了一張表,希望該表的人輸入匹配的用戶名和密碼後,方能登錄。

CREATE TABLE `admin_user`(
`id` int(4) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(100),
`password` VARCHAR(100),
`role` VARCHAR(100),
`realname` VARCHAR(100),
`mobile` VARCHAR(2000),
`state` BIT default 0,
`info` VARCHAR(200),
PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=300;

  塞了幾條數據進去,然後我希望用戶在頁面上進行登錄,那我必須還要創建一個User對象,所謂登錄就是傳入username和password匹配的場景,只要匹配,就登錄成功,跳轉到之前的url

public class User {

    private int id;
    private String name;
    private String password; 省略 getter and setter}

  

public interface UserService {

    User login(String name, String password);
}

  

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public User login(String name, String password) {
        String sql ="select * from admin_user where username =? and password = ?";
        User user =jdbcTemplate.queryForObject(sql,new UserRowMapper(),name,password);
        return user;

    }
}

  

public class UserRowMapper implements RowMapper<User> {
    @Override
    public User mapRow(ResultSet resultSet, int i) throws SQLException {
        //此處要使用表中的字段,不能使用屬性
        int id =resultSet.getInt("id");
        String username = resultSet.getString("username");
        String password = resultSet.getString("password");
        //String role = resultSet.getString("role");

        User user = new User();
        user.setId(id);
        user.setName(username);
        user.setPassword(password);

        return user;
    }
}

  

登錄的方法啪啪啪很快就寫好了,我要怎麽讓系統知道,所有的請求,要先進行登錄呢,登錄的URL是什麽?

先看看別人的代碼,貌似是實現了UserDetailsService 接口,而點進去發現該接口就一個方法

package org.springframework.security.core.userdetails;

public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}

  通過一個String類型的變量val1,獲取用戶的詳細信息。。。怎麽跟我想的不太一樣?

再點進去發現UserDetails 也是一個接口

package org.springframework.security.core.userdetails;

import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

 一個集合,收集權限,結合做過的項目,有的權限是超級管理員,有的權限是普通管理員,又或者有的刪,有新增,有更新等等權限;兩個返回String的方法;

還有判斷賬戶是否過期,被鎖,驗證是否過期,是否開啟了。。。

 看來光看別人的代碼,還是丈二和尚摸不著頭腦呢,去看看官方文檔吧

https://spring.io/projects/spring-security

https://spring.io/guides/topicals/spring-security-architecture

英文原文我就不粘貼了,翻譯過來,大意就是:

應用程序權限歸結於兩個獨立的問題:

1.你是誰

2. 你有什麽樣的權限

一般叫法是權限控制 或者 授權

下面開始講框架中的源碼,通過看源碼可以了解設計的思路

1. 授權策略中主要的接口是AuthenticationManager,並且只有一個方法

public interface AuthenticationManager {

  Authentication authenticate(Authentication authentication)
    throws AuthenticationException;

} 

 驗證管理員在方法authenticate()可以做三件事

a. 輸入的信息是有效的當事人,驗證通過,返回Authentication

b. 輸入的信息是無效的當事人,驗證不通過,返回AuthenticationException

c. 無法判斷的時候,返回一個null

看到這兒,就覺得我想通過查詢 用戶名 = 輸入的用戶名 且 密碼 =輸入密碼的想法真是異想天開了。

Filter Chains,過濾鏈,默認對所有的範文url進行過濾,意味著打開這個網站的任何鏈接,都彈出授權頁面

而如果像如下的例子,則可以在foo下的下url不進行授權驗證,說白了,不登錄,這個url下也可以訪問。 想想日常使用場景,比如總要有個註冊頁面吧,不能全面鏈接都要求登錄。不註冊如何登錄呢?

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.antMatcher("/foo/**")
     ...;
  }
}

  

用戶登錄了之後,要怎麽查看個人信息,傳入@AuthenticationPrincipal,當事人對象Principal principal

@RequestMapping("/foo")
public String foo(@AuthenticationPrincipal User user) {
  ... // do stuff with user
}

 

@RequestMapping("/foo")
public String foo(Principal principal) {
  Authentication authentication = (Authentication) principal;
  User = (User) authentication.getPrincipal();
  ... // do stuff with user
}

  

 這兩天爭取把代碼整理出來,然後貼上github路徑

springboot學習之權限系統登錄驗證SpringSecurity