1. 程式人生 > >springBoot 2.0.3 + SpringSecurity 5.0.6 + thymeleaf + boostrap 許可權管理案例

springBoot 2.0.3 + SpringSecurity 5.0.6 + thymeleaf + boostrap 許可權管理案例

1、 工於成其實,必先搭建springboot工程,配置我們pom.xml 所需的jar依賴         

<!-- thymeleaf 模板依賴 -->

              <dependency>

                     <

groupId>org.springframework.boot</groupId>

                     <artifactId>spring-boot-starter-thymeleaf</artifactId>

              </

dependency>

              <!-- springSecurity 許可權控制依賴 -->

              <dependency>

                     <

groupId>org.springframework.boot</groupId>

                     <artifactId>spring-boot-starter-security</artifactId>

              </dependency>

              <!-- thymeleaf-extras-springsecurity4 該jar必須手動引入 -->

        <dependency>

            <groupId>org.thymeleaf.extras</groupId>

            <artifactId>thymeleaf-extras-springsecurity4</artifactId>

            <version>3.0.2.RELEASE</version><!--$NO-MVN-MAN-VER$-->

        </dependency>

              <!-- mysql資料庫 -->

        <dependency>

               <groupId>mysql</groupId>

               <artifactId>mysql-connector-java</artifactId>

               <scope>runtime</scope>

        </dependency>

       <!-- 引入 jpa.jar --><dependency<groupId>org.springframework.boot</groupId <artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

2、對我們 Application.yml 配置,整個專案環境

spring:

  thymeleaf:

    encoding: UTF-8

    cache: false #熱部署靜態檔案,禁止快取

    mode: HTML5 #使用HTML5標準

#配置資料來源   

  datasource:

    username: root

    password: '123456'

    url: jdbc:mysql://127.0.0.1:3306/springsecurityStudying?characterEncoding=utf-8&useSSL=false                                                        

    driver-class-name: com.mysql.jdbc.Driver

  jpa:

    hibernate:

      ddl-auto: update #自動更新建表

    show-sql: true

    database-platform: org.hibernate.dialect.MySQLDialect # 配置資料庫方言

3、開始編寫我們的所需的SQL指令碼

SET FOREIGN_KEY_CHECKS=0;

DROP TABLE IF EXISTS `authority`;

CREATE TABLE `authority` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `auth_Name` varchar(32) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

INSERT INTO `authority` VALUES ('1', 'ADMIN');

INSERT INTO `authority` VALUES ('2', 'MANAGER');

INSERT INTO `authority` VALUES ('3', 'PRESIDENT');

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `user_name` varchar(32) NOT NULL,

  `pass_word` varchar(99) NOT NULL,

  `email` varchar(50) DEFAULT NULL,

  PRIMARY KEY (`id`),

  UNIQUE KEY `user_name` (`user_name`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

INSERT INTO `user` VALUES ('1', 'baihoo', '$2a$10$N7ME1n6kScoF3NkNaICqFuD2anQpOanTxDiWXIF9qjsgtWnCTXLsi', '[email protected]');

INSERT INTO `user` VALUES ('2', 'baihoo.god', '$2a$10$N7ME1n6kScoF3NkNaICqFuD2anQpOanTxDiWXIF9qjsgtWnCTXLsi', '[email protected]');

INSERT INTO `user` VALUES ('3', 'baihoo.chen', '$2a$10$N7ME1n6kScoF3NkNaICqFuD2anQpOanTxDiWXIF9qjsgtWnCTXLsi', '[email protected]');

INSERT INTO `user` VALUES ('5', 'baiHoo2', '$2a$10$pPreldvox9oX/haR.ugUjuZi8nmLXjcECfEX6BPFPxbIPTvGxAsjG', '[email protected]');

DROP TABLE IF EXISTS `user_authority`;

CREATE TABLE `user_authority` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `user_id` bigint(20) DEFAULT NULL,

  `authority_id` bigint(20) DEFAULT NULL,

  PRIMARY KEY (`id`),

  KEY `user_id` (`user_id`),

  KEY `authority_id` (`authority_id`),

  CONSTRAINT `user_authority_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,

  CONSTRAINT `user_authority_ibfk_2` FOREIGN KEY (`authority_id`) REFERENCES `authority` (`id`) ON DELETE CASCADE ON UPDATE CASCADE

) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

INSERT INTO `user_authority` VALUES ('1', '1', '1');

INSERT INTO `user_authority` VALUES ('2', '1', '2');

INSERT INTO `user_authority` VALUES ('3', '2', '2');

INSERT INTO `user_authority` VALUES ('4', '2', '3');

INSERT INTO `user_authority` VALUES ('5', '3', '1');

INSERT INTO `user_authority` VALUES ('6', '2', '2');

4、熟悉MVC三層架構的小夥伴們,開始編寫我們domain曾實體程式碼

/**

 * 使用者授權角色類

 * @author Administrator

 *

 */

@Entity(name="Authority")

public class Authority  implements GrantedAuthority , Serializable{                                                                                                          

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

         @Size(min = 2, max = 32) @Column(name="auth_name" , nullable = false, length = 20) // 對映為欄位,值不能為空                    

         private String authName;

         public Authority() {

                   super();

         }

         @Override

         public String toString() {

                   return "Authority [id=" + id + ", authName=" + authName + "]";

         }

         public Authority(Long id, String authName) {

                   super();

                   this.id = id;

                   this.authName = authName;

         }

         public Long getId() {

                   return id;

         }

         public void setId(Long id) {

                   this.id = id;

         }

         public String getAuthName() {

                   return authName;

         }

         public void setAuthName(String authName) {

                   this.authName = authName;

         }

         @Override

         public String getAuthority() {

                   //許可權名稱

                   return authName;

         }

}

/**

 * 使用者實體

 *

 * @author Administrator

 *

 */

@Entity(name="user") // 實體

public class User implements UserDetails, Serializable {

 

         @Id @GeneratedValue(strategy = GenerationType.IDENTITY) // 自動增長

         private Long id; // 實體一個唯一標識

         @Size(min = 2, max = 32) @Column(name="user_name" , nullable = false, length = 20) // 對映為欄位,值不能為空                    

         private String username;

         @Size(max = 99) @Column(name="pass_word" , length = 99)

         private String password;

         @Size(max = 50) @Email

         @Column(nullable = false, length = 50, unique = true)

         private String email;

         @ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.EAGER)

         /**

          * 加入中間表user_authority

          *              中間表加入列user_id,參考列為當前主鍵列

          *              中間表加入列authority_id, 參考當前表倒置到Authority表的主鍵列

          */

         @JoinTable(name = "user_authority",

                                                        joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),

                                                        inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id"))

    private List<Authority> authorities;

         public User() {

 

         }

         public User(Long id, String username, String password, String email) {

                   super();

                   this.id = id;

                   this.username = username;

                   this.password = password;

                   this.email = email;

         }

         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;

         }

         /**

          * 密碼BCrypt加密

          * @param password

          */

         public void setPassword(String password) {

        PasswordEncoder  encoder = new BCryptPasswordEncoder();

        String encodePasswd = encoder.encode(password);

        this.password = encodePasswd;

         }

         public String getEmail() {

                   return email;

         }

         public void setEmail(String email) {

                   this.email = email;

         }

         /**

          * 需將 List<Authority> 轉成 List<SimpleGrantedAuthority>,否則前端拿不到角色列表名稱

          */

         @Override

         public Collection<? extends GrantedAuthority> getAuthorities() {

        List<SimpleGrantedAuthority> simpleAuthorities = new ArrayList<>();

        for(GrantedAuthority authority : this.authorities){

            simpleAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));

        }

        return simpleAuthorities;

         }

         @Override

         public boolean isAccountNonExpired() {

                   //過載預設是false,我們要改成true

                   return true;

         }

         @Override

         public boolean isAccountNonLocked() {

                   //過載預設是false,我們要改成true

                   return true;

         }

         @Override

         public boolean isCredentialsNonExpired() {

                   //過載預設是false,我們要改成true

                   return true;

         }

         @Override

         public boolean isEnabled() {

                   //過載預設是false,我們要改成true

                   return true;

         }

         @Override

         public String toString() {

                   return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email

                                     + ", authorities=" + authorities + "]";

         }

}

 

編寫我們repository層的程式碼

/**

 * 實現JPA介面類

 * @author Administrator

 *

 */

public interface AuthorityRepository extends JpaRepository<Authority, Long>{                                                                                          

}

/**

 * UserRepository 介面

 * @author Administrator

 *

 */

public interface UserRepository  extends JpaRepository<User, Long>{                                                                                                    

              /**

               * 通過名稱查詢使用者

               * @param username

               * @return

               */

              public User findByUsername(String username);

              /**

               * 通過使用者名稱和密碼查詢使用者

               * @param username

               * @param password

               * @return

               */

              public User findByUsernameAndPassword(String username , String password);

}

 編寫我們service層的程式碼

/**

 *

 * UserService 服務層<br>

 * UserService 實現 UserDetailsService 介面,重寫其方法!這是必須<br>

 *

 * @author Administrator

 *

 */

@Service("userservice")

@SuppressWarnings("all")

public class UserService implements UserDetailsService{                                                                                                                           

         @Autowired

         UserRepository userRepository;     

         @Override

         public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

                   User user = userRepository.findByUsername(username);

                   if(user == null ) {

                            throw new UsernameNotFoundException("使用者名稱不存在");

                   }

                   Boolean locked = user.isAccountNonLocked();               

                   return user;

         }

         public User findByUsernameAndPassword(String username , String password) {

                   return userRepository.findByUsernameAndPassword(username, password);

         }

}

/**

 *

 * @author Administrator

 *

 */

public class AuthorityService {                                                                                                                                                                   

}

 編寫我們controller層的程式碼

/**

 * 主頁控制器

 * @author Administrator

 *

 */

@Controller

public class MainController {                                                                                                                                                                      

         @Autowired

         @Qualifier("userRepository")

         private UserRepository userRepository;

         /**

          * 根目錄控制

          * @return

          */

         @GetMapping("/")

         public String root() {

                   return "redirect:/index";

         }

         /**

          * 網站首頁

          * @return

          */

         @GetMapping("/index")

         public String index() {

                   return "index"; //index.html

         }

         /**

          * 登陸介面

          * @return

          */

         @GetMapping("/login")

         public String login() {

                   return "login"; //login.html

         }

         /**

          * 403錯誤介面

          * @return

          */

         @GetMapping("/403")

    public String error403() {

        return "/error/403";

    }

         /**

          * 登陸錯誤,返回登陸頁面,並新增錯誤資訊

          * @param model

          * @return

          */

         @GetMapping("/login-error")

         public String loginError(Model model , HttpSession session , @RequestParam(value = "secError", required = true) Boolean secError) {

                   model.addAttribute("loginError" , true);

                   //獲取其service層獲取登陸使用者丟擲的異常資訊

                   Exception exception = (Exception)session.getAttribute("SPRING_SECURITY_LAST_EXCEPTION");

                   model.addAttribute("errorMessage" ,exception.getMessage());

                   return "login";

         }

}

/**

 * 使用者控制層

 *

 * @author Administrator

 *

 */

@RestController

@RequestMapping("/user")

public class UserController {                                                                                                                                                                        

         @Autowired

         @Qualifier("userRepository")

         private UserRepository userRepository;

         /**

          * 頁面獲取使用者列表

          *

          * @param model

          * @return

          */

         @GetMapping("/list")

         public ModelAndView list(Model model) {

                   model.addAttribute("userList", userRepository.findAll());

                   model.addAttribute("title", "使用者管理");

                   return new ModelAndView("users/list", "userModel", model);

         }

         /**

          * 根據id查詢使用者並頁面展示

          *

          * @param id

          * @param model

          * @return

          */

         @GetMapping("/view/{id}")

         public ModelAndView view(@PathVariable("id") Long id, Model model) {

                   Optional<User> userOp = userRepository.findById(id);

                   model.addAttribute("user", userOp.get());

                   model.addAttribute("title", "檢視使用者");

                   return new ModelAndView("users/view", "userModel", model);

         }

         /**

          * 獲取建立表單頁面

          *

          * @param model

          * @return

          */

         @GetMapping("/form")

         public ModelAndView createForm(Model model) {

                   model.addAttribute("user", new User());

                   model.addAttribute("title", "建立使用者");

                   return new ModelAndView("users/form", "userModel", model);

         }

         /**

          * 儲存使用者

          * @param user

          * @return

          */

         @PostMapping("/submit")

         public ModelAndView saveOrUpdateUser(User user) {

                   user = userRepository.save(user);

                   ModelAndView mav = new ModelAndView();

                   mav.setViewName("redirect:list");// 重定向至list對映方法

                   return mav;

         }

         /**

          * 根據id查詢使用者帶參並跳轉到form頁面

          *

          * @param id

          * @param model

          * @return

          */

         @GetMapping("/modify/{id}")

         public ModelAndView modifyUser(@PathVariable("id") Long id, Model model) {

                   Optional<User> userOp = userRepository.findById(id);

                   model.addAttribute("user", userOp.get());

                   model.addAttribute("title", "修改使用者");

                   return new ModelAndView("users/form", "userModel", model);

         }

         /**

          * 根據id刪除使用者

          *

          * @param id

          * @param model

          * @return

          */

         @GetMapping("/delete/{id}")

         public ModelAndView deleteUser(@PathVariable("id") Long id, Model model) {

                   userRepository.deleteById(id);

                   ModelAndView mav = new ModelAndView();

                   mav.setViewName("redirect:/user/list");// 重定向至list對映方法

                   return mav;

         }

}

 既然要做許可權控制,那麼我們肯定就要編寫springSecurity配置類

/**

 * springSecurity安全配置類

 *              注意:該類上的註解包含"@Configuration"因此只會被初始化載入<