zoukankan      html  css  js  c++  java
  • SpringBoot + Security实现权限控制

    网上找了好几个,因为各种原因不太行,下面这个亲测可行

    参考:https://blog.csdn.net/u012702547/article/details/54319508

    基于SpringBoot + JPA

    安全框架:Security5

    页面:Thymeleaf + BootStrap

    工程目录结构:

     引入依赖包

    pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.zit</groupId>
      <artifactId>Hello</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.0.RELEASE</version>
        </parent>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            
            <dependency>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-data-jpa</artifactId>
             </dependency>
             
             <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
             
             <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity4</artifactId>
            </dependency>
             
             <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.40</version>
            </dependency>
            
        </dependencies>
        
        <repositories>
            <repository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/libs-snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
    
    </project>

     配置文件

    application.properties

    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
    spring.datasource.username=root
    spring.datasource.password=
    logging.level.org.springframework.security=info
    spring.thymeleaf.cache=false
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    spring.jackson.serialization.indent_output=true
    
    spring.thymeleaf.cache=false
     

    1、实体类

    (1)用户

    package com.zit;
    
    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> roles;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public List<SysRole> getRoles() {
            return roles;
        }
    
        public void setRoles(List<SysRole> roles) {
            this.roles = roles;
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            List<GrantedAuthority> auths = new ArrayList<>();
            List<SysRole> roles = this.getRoles();
            for (SysRole role : roles) {
                auths.add(new SimpleGrantedAuthority(role.getName()));
            }
            return auths;
        }
    
        @Override
        public String getPassword() {
            return this.password;
        }
    
        @Override
        public String getUsername() {
            return this.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;
        }
    }

    (2)角色

    package com.zit;
    
    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;
        }
    }

    2、JPA访问数据库

    package com.zit;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface SysUserRepository extends JpaRepository<SysUser, Long> {
        SysUser findByUsername(String username);
    }

    3、控制器

    (1)控制器给页面传值的对象

    package com.zit;
    
    /**
     * 传递在页面上的消息
     */
    public class Msg {
        private String title;
        private String content;
        private String extraInfo;
    
        public Msg() {
        }
    
        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 getExtraInfo() {
            return extraInfo;
        }
    
        public void setExtraInfo(String extraInfo) {
            this.extraInfo = extraInfo;
        }
    
        public Msg(String title, String content, String extraInfo) {
            this.title = title;
            this.content = content;
            this.extraInfo = extraInfo;
        }
    }

    (2)控制类

    package com.zit;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HomeController {
        @RequestMapping("/")
        public String index(Model model) {
            Msg msg = new Msg("测试标题", "测试内容", "额外信息,只对管理员显示");
            model.addAttribute("msg", msg);
            return "index";
        }
    }

    4、自定义UserDetailsService

    package com.zit;
    
    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 CustomUserService implements UserDetailsService {
        @Autowired
        SysUserRepository userRepository;
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            SysUser user = userRepository.findByUsername(s);
            if (user == null) {
                throw new UsernameNotFoundException("用户名不存在");
            }
            System.out.println("s:"+s);
            System.out.println("username:"+user.getUsername()+";password:"+user.getPassword());
            return user;
        }
    }

    5、SpringMVC配置

    package com.zit;
    
    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时跳转到login.html页面

    6、配置Spring Security

    由于Spring Security5必须自定义密码加密,所以建立一个自定义密码加密类

    (1)MyPasswordEncoder.java

    package com.zit;
    
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    public class MyPasswordEncoder implements PasswordEncoder {
    
        @Override
        public String encode(CharSequence arg0) {
            return arg0.toString();
        }
    
        @Override
        public boolean matches(CharSequence arg0, String arg1) {
            return arg1.equals(arg0.toString());
        }
    
    }

    (2)Security配置

    package com.zit;
    
    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 WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Bean
        UserDetailsService customUserService() {
            return new CustomUserService();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(customUserService())
            .passwordEncoder(new MyPasswordEncoder());
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                //security允许页面加载css文件夹下的静态资源
                .antMatchers("/css/**").permitAll()
                    .anyRequest().authenticated()
                    .and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
                    .and()
                    .logout()
                    .permitAll();
        }
    }

    1.首先当我们要自定义Spring Security的时候我们需要继承自WebSecurityConfigurerAdapter来完成,相关配置重写对应 方法即可。 
    2.我们在这里注册CustomUserService的Bean,然后通过重写configure方法添加我们自定义的认证方式。 
    3.在configure(HttpSecurity http)方法中,我们设置了登录页面,而且登录页面任何人都可以访问,然后设置了登录失败地址,也设置了注销请求,注销请求也是任何人都可以访问的。 
    4.permitAll表示该请求任何人都可以访问,.anyRequest().authenticated(),表示其他的请求都必须要有权限认证。 

    7、静态资源

    (1)CSS

    下载bootstrap包,取其bootstrap.min.css

    另,自己写一个signin.css,如下:

    body {
        padding-top: 40px;
        padding-bottom: 40px;
        background-color: #eee;
    }
    
    .form-signin {
        max- 330px;
        padding: 15px;
        margin: 0 auto;
    }
    .form-signin .form-signin-heading,
    .form-signin .checkbox {
        margin-bottom: 10px;
    }
    .form-signin .checkbox {
        font-weight: normal;
    }
    .form-signin .form-control {
        position: relative;
        height: auto;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
        padding: 10px;
        font-size: 16px;
    }
    .form-signin .form-control:focus {
        z-index: 2;
    }
    .form-signin input[type="email"] {
        margin-bottom: -1px;
        border-bottom-right-radius: 0;
        border-bottom-left-radius: 0;
    }
    .form-signin input[type="password"] {
        margin-bottom: 10px;
        border-top-left-radius: 0;
        border-top-right-radius: 0;
    }

    (2)HTML

    login.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8"/>
        <title>登录</title>
        <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/>
        <link rel="stylesheet" th:href="@{css/signin.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>
                    <li><a th:href="@{http://www.baidu.com}">百度</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container">
        <div class="starter-template">
            <p th:if="${param.logout}" class="bg-warning">已注销</p>
            <p th:if="${param.error}" class="bg-danger">有错误,请重试</p>
            <h2>使用账号密码登录</h2>
            <form class="form-signin" role="form" name="form" th:action="@{/login}" action="/login" method="post">
                <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>

    index.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
    <head>
        <meta charset="UTF-8"/>
        <title sec:authentication="name"></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>
                    <li><a th:href="@{http://www.baidu.com}">百度</a></li>
                </ul>
            </div>
        </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')">
                <p class="bg-info" th:text="${msg.extraInfo}"></p>
            </div>
            <div sec:authorize="hasRole('ROLE_USER')">
                <p class="bg-info">无更多显示信息</p>
            </div>
            <form th:action="@{/logout}" method="post">
                <input type="submit" class="btn btn-primary" value="注销"/>
            </form>
        </div>
    </div>
    </body>
    </html>
  • 相关阅读:
    164 Maximum Gap 最大间距
    162 Find Peak Element 寻找峰值
    160 Intersection of Two Linked Lists 相交链表
    155 Min Stack 最小栈
    154 Find Minimum in Rotated Sorted Array II
    153 Find Minimum in Rotated Sorted Array 旋转数组的最小值
    152 Maximum Product Subarray 乘积最大子序列
    151 Reverse Words in a String 翻转字符串里的单词
    bzoj3994: [SDOI2015]约数个数和
    bzoj 4590: [Shoi2015]自动刷题机
  • 原文地址:https://www.cnblogs.com/Donnnnnn/p/8716247.html
Copyright © 2011-2022 走看看