springboot+springsecurity基礎配置(二)

繼續上一篇博客的項目,向下擴展

 

springsecurity中所有配置基本都來源於一個默認的WebSecurityConfigurerAdapter

所以我們要寫一個類來繼承它,放棄默認配置

叫SecurityConfig

 

添加一個login.html登錄頁面,登錄成功以後跳到之前寫的hello.html頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login page</title>
</head>
<body>
This is login page
<form action="/login" method="post">
    username: <input name="username" /><br/>
    password: <input name="password" /><br/>
    <button type="submit">submit</button>
</form>
</body>
</html>

這個提交地址/login比較有意義,後面會用到配置

然後我們開始配置SecurityConfig

package com.security.securitydemo.security;

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;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @Author WQY
 * @Date 2019/11/27 9:44
 * @Version 1.0
 */
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login")
                // 和login.html中表單提交的一直必須一樣,這樣才能讓springsecurity幫你處理請求
                .loginProcessingUrl("/login")
                .and()
                .authorizeRequests()
                //添加不需要過濾的地址
                .antMatchers("/index", "/login", "/error").permitAll()
                .anyRequest()
                .authenticated();
    }

}

 

然後啓動項目訪問http://localhost:8880

就會出現自定義的登錄界面

然後輸入用戶名密碼後會出現403

不急別慌,因爲開啓了debug所以能在控制檯看見走了一個CrsfFilter,這個filter需要一個參數,防止xss攻擊的,但是我們不需要,所以我們禁掉。

修改SecurityConfig。

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login")
                // 和login.html中表單提交的一直必須一樣,這樣才能讓springsecurity幫你處理請求
                .loginProcessingUrl("/login")
                .and()
                .authorizeRequests()
                .antMatchers("/index", "/login", "/error").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();
    }

在登陸就不會有403的錯誤了

但是會出現404的錯誤

因爲沒有設置登錄成功的頁面,所以http://localhost:8080作爲了默認頁面

然後我們在

SecurityConfig

中添加一個登錄成功頁面

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login")
                // 和login.html中表單提交的一直必須一樣,這樣才能讓springsecurity幫你處理請求
                .loginProcessingUrl("/login")
                .successForwardUrl("/hello")
                .and()
                .authorizeRequests()
                .antMatchers("/index", "/login", "/error").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();
    }

可是這樣我這會出現405

在修改SecurityConfig文件,添加默認成功頁面

@Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login")//處理登錄請求接口
                .successForwardUrl("/hello")
                .defaultSuccessUrl("/hello",true)
                .and()
                .authorizeRequests()
                .antMatchers("/index","/login","/error").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();

    }

這樣輸入賬號密碼後就進來了

 

自定義數據查詢

經過上面的配置,我們實現了自定義登錄頁,但是數據是寫死的

所以現在要從數據庫獲取用戶信息

比如我們的數據庫一共有兩張表,user表和role表

package com.security.securitydemo.entity;


import lombok.Data;

import javax.persistence.*;
import java.util.Date;

/**
 * @Description  
 * @Author  WQY
 * @Date 2019-11-05 
 */
@Data
@Entity
@Table ( name ="user" )
public class UserEntity{

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

	/**
	 * 用戶名
	 */
   	@Column(name = "username" )
	private String username;

	/**
	 * 密碼
	 */
   	@Column(name = "password" )
	private String password;

	/**
	 * 保存時間
	 */
   	@Column(name = "savetime" )
	private Date savetime;

	/**
	 * 手機號
	 */
   	@Column(name = "iphone" )
	private String iphone;

	/**
	 * 權限
	 */
   	@Column(name = "authority" )
	private Long authority;

	/**
	 * 性別,1男,2女
	 */
   	@Column(name = "sex" )
	private String sex;

	/**
	 * 組織機構編號
	 */
   	@Column(name = "organization_num" )
	private String organizationNum;

	/**
	 * 組織機構名稱
	 */
   	@Column(name = "organization_name" )
	private String organizationName;
}
package com.security.securitydemo.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * @Description  
 * @Author  WQY
 * @Date 2019-11-25 
 */
@Data
@Entity
@Table ( name ="role" )
public class RoleEntity  {

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

   	@Column(name = "name" )
	private String name;


}

並建立他們的Repository

package com.security.securitydemo.dao;


import com.security.securitydemo.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author WQY
 * @date 2019/9/9 15:28
 */
public interface User_Jpa extends JpaRepository<UserEntity,Integer> {

    UserEntity findByUsername(String username);

}
package com.security.securitydemo.dao;


import com.security.securitydemo.entity.RoleEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

/**
 * @Author WQY
 * @Date 2019/11/25 17:10
 * @Version 1.0
 */
public interface Role_Jpa extends JpaRepository<RoleEntity,Long> {

    @Query(value = "select d from RoleEntity d where d.id=?1")
    RoleEntity selectById(Long id);
}

基礎項寫完以後就要與sprinsecurity結合了

springsecurity中對於用戶的表示有自己的實體類相對應,它就是UserDetails,所以我們編寫一個AuthUser實現這個接口:

package com.security.securitydemo.security.entity;

import com.security.securitydemo.entity.RoleEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author WQY
 * @Date 2019/11/26 14:52
 * @Version 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AuthUser implements UserDetails {

    private String username;
    private String password;
    private List<RoleEntity> roles;


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles.isEmpty() ? Collections.EMPTY_LIST :
// ROLE_ 是springsecurity對於角色的默認前綴,如果不加,驗證會失敗
                (roles.parallelStream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList()));    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    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;
    }
}

其中關於賬號過期,enable全部設置爲通過,接下來就是編寫CustomUserDetailsService,返回我們自己的AuthUser:

package com.security.securitydemo.security.impl;


import com.security.securitydemo.dao.Role_Jpa;
import com.security.securitydemo.dao.User_Jpa;
import com.security.securitydemo.entity.UserEntity;
import com.security.securitydemo.security.entity.AuthUser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;

/**
 * @Author WQY
 * @Date 2019/11/26 14:55
 * @Version 1.0
 */
@Service
@Primary
public class CustomUserDetailsServiceImpl implements UserDetailsService {
    @Resource
    private User_Jpa userRepository;

    @Resource
    private Role_Jpa roleRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity user = userRepository.findByUsername(username);

        if (user == null) {
            throw new UsernameNotFoundException("user: " + username + " is not found.");
        }

        return new AuthUser(user.getUsername(), user.getPassword(), roleRepository.findAllById(Collections.singletonList(user.getAuthority())));
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        System.out.println(bCryptPasswordEncoder.encode("123456"));
    }

}

到此,其實我們的UserDetails已經注入了Spring中,其實我們加上@Service和@Primary之後,springsecurity就能自己檢測到這個bean,然後作爲自己的UserDetailsService。

因爲加了加密,所以先用main方法對123456加密,然後放入數據庫

最後是一個修改controller

package com.security.securitydemo.controller;

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

/**
 * @Author WQY
 * @Date 2019/11/27 9:31
 * @Version 1.0
 */
@Controller
@RequestMapping
public class HelloController {

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

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

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

然後在訪問頁面輸入admin和123456(自己定義以後的)

就會進入hello.html頁面,由於在

SecurityConfig

中配置了幾個放行的頁面所以直接訪問http://localhost:8880/index也行

因爲他不需要權限

項目地址:https://download.csdn.net/download/qq_41755287/12000491

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章