1. 程式人生 > >spring boot security的簡單學習demo

spring boot security的簡單學習demo

專案的目錄結構如圖
這裡寫圖片描述

bootstrap.min.css自己上網上找到下載吧

pom.xml

<!-- Spring Boot 啟動父依賴 核心模組,包括自動配置支援、日誌和YAML-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version
>
</parent> <dependencies> <!--start-web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--jpa-->
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!--security--> <dependency> <groupId>org.springframework.boot</groupId
>
<artifactId>spring-boot-starter-security</artifactId> </dependency> <!--Thymeleaf--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <!--jdbc--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>javax.batch</groupId> <artifactId>javax.batch-api</artifactId> <version>1.0.1</version> </dependency> <!--Thymeleaf的spring security的支援--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> </dependencies>

application.properties檔案

# 設定埠號
server.port=8080
# 設定日誌級別
logging.level.root=info
# 資料來源配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://ip:3306/dbname?useUnicode=true&amp;characterEncoding=UTF-8
spring.datasource.username=
spring.datasource.password=
# 讓控制器輸出json字串格式
spring.jackson.serialization.indent-output=true
# 
spring.jpa.hibernate.ddl-auto=update
# 顯示sql語句
spring.jpa.show-sql=true
# security日誌配置
logging.level.org.springframework.security=debug
# thymeleaf模板快取設定
spring.thymeleaf.cache=false

啟動類

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringSecurityContext {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityContext.class);
    }
}

domian
SysRole

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 * 角色
 */
@Entity
public class SysRole {

    @Id
    @GeneratedValue
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

SysUser

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

import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 使用者
 */
@Entity
public class SysUser implements UserDetails {

    @Id
    @GeneratedValue
    private Long id;
    private String username;
    private String password;
    @ManyToMany(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER) // 配置使用者和角色的多對多關係
    private List<SysRole> sysRoles;

    @Override // 將使用者的角色作為許可權
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> auths = new ArrayList<>();
        List<SysRole> roles = this.getSysRoles();
        for (SysRole role : roles) {
            auths.add(new SimpleGrantedAuthority(role.getName()));
        }
        return auths;
    }

    @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 Long getId() {
        return id;
    }

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

    @Override
    public String getUsername() {
        return username;
    }

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

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

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

    public List<SysRole> getSysRoles() {
        return sysRoles;
    }

    public void setSysRoles(List<SysRole> sysRoles) {
        this.sysRoles = sysRoles;
    }
}

Msg

public class Msg {
    private String title;
    private String content;
    private String etraInfo;

    public Msg(String title, String content, String etraInfo) {
        super();
        this.title = title;
        this.content = content;
        this.etraInfo = etraInfo;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getEtraInfo() {
        return etraInfo;
    }

    public void setEtraInfo(String etraInfo) {
        this.etraInfo = etraInfo;
    }

}

dao

import cn.zfs.springboot.security.domain.SysUser;
import org.springframework.data.jpa.repository.JpaRepository;

public interface SysUserRepository extends JpaRepository<SysUser,Long> {

    SysUser findByUsername(String username);
}

service

import cn.zfs.springboot.security.dao.SysUserRepository;
import cn.zfs.springboot.security.domain.SysUser;
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;

public class CustomerUserService implements UserDetailsService {

    @Autowired
    private SysUserRepository sysUserRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserRepository.findByUsername(username);
        if(sysUser == null){
            throw new UsernameNotFoundException("使用者名稱不存在");
        }
        return sysUser;
    }
}

配置類
securityConfig

import cn.zfs.springboot.security.service.CustomerUserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Bean
    UserDetailsService customerUserService(){
        return new CustomerUserService();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customerUserService());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated() // 所有請求頁面都需要登入才能訪問
                .and()
                .formLogin()
                    .loginPage("/login")
                    .failureForwardUrl("/login?error")
                    .permitAll() // 定製登入行為,登入頁面可以任意訪問
                .and()
                .logout().permitAll(); // 定製登出行為,登出請求可以任意訪問
    }
}

WebMvcConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class WebMVCConfig extends WebMvcConfigurerAdapter{

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login"); // 註冊訪問轉向login.HTML頁面
    }
}

Controller

import cn.zfs.springboot.security.domain.Msg;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class SecurityController {

    @RequestMapping("/")
    public String index(Model model){
        Msg msg = new Msg("測試標題","測試內容","額外資訊,只對管理員顯示");
        model.addAttribute("msg",msg);
        return "home";
    }
}

home.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" 
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"><!-- 1 -->
<head>
<meta content="text/html;charset=UTF-8"/>
<title sec:authentication="name"></title> <!-- 2 -->
<link rel="stylesheet" th:href="@{css/bootstrap.min.css}" />
<style type="text/css">
body {
  padding-top: 50px;
}
.starter-template {
  padding: 40px 15px;
  text-align: center;
}
</style>
</head>
<body>
     <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <a class="navbar-brand" href="#">Spring Security演示</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
           <li><a th:href="@{/}"> 首頁 </a></li>

          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav>


     <div class="container">

      <div class="starter-template">
        <h1 th:text="${msg.title}"></h1>

        <p class="bg-primary" th:text="${msg.content}"></p>

        <div sec:authorize="hasRole('ROLE_ADMIN')"> <!-- 3 -->
            <p class="bg-info" th:text="${msg.etraInfo}"></p>
        </div>  

        <div sec:authorize="hasRole('ROLE_USER')"> <!-- 4-->
            <p class="bg-info">無更多資訊顯示</p>
        </div>  

        <form th:action="@{/logout}" method="post">
            <input type="submit" class="btn btn-primary" value="登出"/><!-- 5 -->
        </form>
      </div>

    </div>


</body>
</html>

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta content="text/html;charset=UTF-8"/>
<title>登入頁面</title>
<link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/>
<style type="text/css">
    body {
  padding-top: 50px;
}
.starter-template {
  padding: 40px 15px;
  text-align: center;
}
</style>
</head>
<body>

     <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <a class="navbar-brand" href="#">Spring Security演示</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
           <li><a th:href="@{/}"> 首頁 </a></li>

          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav>
     <div class="container">

      <div class="starter-template">
       <p th:if="${param.logout}" class="bg-warning">已成功登出</p><!-- 1 -->
            <p th:if="${param.error}" class="bg-danger">有錯誤,請重試</p> <!-- 2 -->
            <h2>使用賬號密碼登入</h2>
            <form name="form" th:action="@{/login}" action="/login" method="POST"> <!-- 3 -->
                <div class="form-group">
                    <label for="username">賬號</label>
                    <input type="text" class="form-control" name="username" value="" placeholder="賬號" />
                </div>
                <div class="form-group">
                    <label for="password">密碼</label>
                    <input type="password" class="form-control" name="password" placeholder="密碼" />
                </div>
                <input type="submit" id="login" value="Login" class="btn btn-primary" />
            </form>
      </div>

    </div>

</body>
</html>

注:學自 <<javaEE 開發的顛覆者 spring boot 實戰>>