Springboot整合Security实现登录权限验证

绪:

             通过这个查,参照别人的demo实现了security权限认证,可能有些地方写的不对,供参考!希望对你有帮助

本文参照 https://www.cnblogs.com/ealenxie/p/9293768.html

一.配置

    1.pom配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         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.zhaoyu.spingbootSecurity</groupId>
    <artifactId>practice1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>practice1</name>
    <description>Demo project for Spring Boot and Security</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--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>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--security和thymeleaf整合的-->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>
        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--web支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--H2内存数据库-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>

        </plugins>
    </build>


</project>

添加了WEB、JPA、Thymeleaf、H2、SpringSecurity的pom

1.application.properties配置

server.port=80
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache=false
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
#h2
#spring.h2.console.path=/h2
#spring.h2.console.enabled=true
#spring.datasource.url=jdbc:h2:~/test4;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE
#spring.datasource.driver-class-name: com.mysql.jdbc.Driver

spring.datasource.url: jdbc:mysql://localhost:3306/forsecurity?useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver

二、代码部分

1.User实体实现了序列化、UserDetails、GrantedAuthority

    序列化为了持久化

  UserDetails为了权限开放

  GrantedAuthority为了指定权限(感觉就是告诉哪个是关键字)

package com.zhaoyu.spingbootsecurity.practice1.domain;

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

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

@Entity
public class User implements Serializable,UserDetails,GrantedAuthority {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(length = 20)
    private String username;
    @Column(length = 200)
    private String password;
    @Column(length = 40)
    private String email;
    @Column(length = 20)
    private String role;//权限


    protected User() {
    }


    public User(String username, String password, String email) {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public Collection<? extends GrantedAuthority> getAuthorities() {
        //  需将 List<Authority> 转成 List<SimpleGrantedAuthority>,否则前端拿不到角色列表名称
        List<SimpleGrantedAuthority> simpleAuthorities = new ArrayList<>();
        if(this.role.contains(",")){
            simpleAuthorities.add(new SimpleGrantedAuthority(this.getAuthority()));
        }
        String [] roles=this.getAuthority().split(",");
        for (String role:roles
             ) {
            simpleAuthorities.add(new SimpleGrantedAuthority(role));
        }
        return simpleAuthorities;
    }

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

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

    public void setUsername(String username) {
        this.username = 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;
    }

    public Long getId() {
        return id;
    }

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

    public void setBCryptPassword(String password) {
        this.password =new BCryptPasswordEncoder(4).encode(password);
    }
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

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

    public void setRole(String role) {
        this.role = role;
    }

    @Override
    public String getAuthority() {
        return role;
    }
}

    2.Controller

package com.zhaoyu.spingbootsecurity.practice1.controller;


import com.zhaoyu.spingbootsecurity.practice1.domain.User;
import com.zhaoyu.spingbootsecurity.practice1.repository.UserRepository;
import com.zhaoyu.spingbootsecurity.practice1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;


@Controller
@RequestMapping("/index")
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserService userService;

    @GetMapping
    public String toIndex(Model model) {
        List<User> users = userRepository.findAll();
        model.addAttribute("users", users);
        return "/index";
    }

    @PostMapping("/toindex")
    public ModelAndView loginEnd(User user) {

        User user2 = userService.login(user);
        if (user2 != null) {
            return new ModelAndView("redirect:/index", "loginUser", user2);
        }

        return new ModelAndView("login", "loginFail", "登录失败");
    }

    @GetMapping("delete/{id}")
    public String deleteUser(@PathVariable Long id){
        userRepository.deleteById(id);
        return "redirect:/index";
    }
    @GetMapping("/{id}")
    public String getUser(Model model,@PathVariable Long id) {
        User user = userRepository.findById(id).get();
        model.addAttribute("one", user);
        return "/userInfo";
    }

    @PostMapping("/add")
    public String addUser(User user) {
        user.setBCryptPassword(user.getPassword());
        userRepository.save(user);
        System.out.println("保存了");
        return "redirect:/index";
    }

    @GetMapping("/touserForm")
    public String addUser() {
        return "/userForm";
    }
}

    负责各种接口

3.repository

package com.zhaoyu.spingbootsecurity.practice1.repository;

import com.zhaoyu.spingbootsecurity.practice1.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    public User findUserByIdAndUsername(Long id, String name);

    public User findByUsernameAndPassword(String name, String possword);


    public User findByUsername(String name);
}

    提供数据库操作支持

4.WebSecurityConfig配置

package com.zhaoyu.spingbootsecurity.practice1.condig;

import com.zhaoyu.spingbootsecurity.practice1.domain.User;
import com.zhaoyu.spingbootsecurity.practice1.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.method.configuration.EnableGlobalMethodSecurity;
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.security.core.Authentication;
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.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);

    @Override
    protected void configure(HttpSecurity http) throws Exception { //配置策略
        http.csrf().disable();
        http.authorizeRequests().
                antMatchers("/static/**").permitAll().anyRequest().authenticated().
                and().formLogin().loginPage("/tologin").loginProcessingUrl("/login").permitAll().successHandler(loginSuccessHandler()).
                and().logout().permitAll().invalidateHttpSession(true).
                deleteCookies("JSESSIONID").logoutSuccessHandler(logoutSuccessHandler()).
                and().sessionManagement().maximumSessions(10).expiredUrl("/tologin");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailsService());//.passwordEncoder(passwordEncoder())
      auth.eraseCredentials(false);

       //auth.inMemoryAuthentication().withUser("123").password(new BCryptPasswordEncoder(4).encode("123")).roles("user");
       // auth.inMemoryAuthentication().withUser("111").password(new BCryptPasswordEncoder(4).encode("111")).roles("admin");
    }


    @Bean
    public BCryptPasswordEncoder passwordEncoder() { //密码加密
        return new BCryptPasswordEncoder(4);
    }

    @Bean
    public LogoutSuccessHandler logoutSuccessHandler() { //登出处理
        return new LogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                try {
                    User user = (User) authentication.getPrincipal();
                    logger.info("USER : " + user.getUsername()+ " LOGOUT SUCCESS !  ");
                } catch (Exception e) {
                    logger.info("LOGOUT EXCEPTION , e : " + e.getMessage());
                }
                httpServletResponse.sendRedirect("/tologin");
            }
        };
    }

    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler loginSuccessHandler() { //登入处理
        return new SavedRequestAwareAuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                UserDetails userDetails = (UserDetails) authentication.getPrincipal();
                logger.info("USER : " + userDetails.getUsername() + " LOGIN SUCCESS !  ");
               response.sendRedirect("/index");
                super.onAuthenticationSuccess(request, response, authentication);
            }
        };
    }
    @Bean
    public UserDetailsService userDetailsService() {    //用户登录实现
        return new UserDetailsService() {
            @Autowired
            private UserRepository userRepository;

            @Override
            public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
                User user = userRepository.findByUsername(s);
                if (user == null){
                    throw new UsernameNotFoundException("Username " + s + " not found");
                }

//                Collection<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
//                authorities.add(new SimpleGrantedAuthority("user"));
                return user;
            }
        };


    }
}

5.login.html

<form th:action="@{/login}" method="post">
    账号:
    <input type="text" name="username"><br>
    密码:
    <input type="password" name="password"><br>
    <input type="submit" value="提交"><br>

</form>

6.index.html(主页)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
    <style type="text/css">


        table {
            margin: 50px auto;
            border: solid 1px black;
            width: 1200px;
        }
        td{
            border: solid 1px black;
            height: 20px;
            text-align: center;
            line-height: 20px;
            padding: 0;
        }
    </style>
</head>
<script src="/static/jquery-3.3.1.min.js" th:src="@{/jquery-3.3.1.min.js}"></script>

<body>
<h3><a th:href="@{/index/touserForm}">添加</a></h3>
<h3 sec:authorize="hasRole('ROLE_ADMIN')">欢迎管理员登录</h3>
<h3 sec:authorize="hasRole('ROLE_USER')">欢迎普通人员员登录</h3>
<a  th:href="@{/admin}" sec:authorize="hasRole('ROLE_ADMIN')">去管理员页面</a>

<button th:href="@{/tologin}">退出登录</button>
    <div>
        <table cellpadding="0" cellspacing="0">
            <caption>个人信息表</caption>
            <thead>

                <td>id</td>
                <td>账号</td>
                <td>密码</td>
                <td>邮箱</td>
                <td>操作</td>

            </thead>
            <tbody>
            <tr th:if="${users.size()} eq 0">
                <td th:colspan="5">暂时没有用户信息</td>
            </tr>
            <tr th:each="user:${users}" th:object="${user}">
                <td th:text="*{id}" id="id">1</td>
                <td th:text="*{username}" id="username">赵宇</td>
                <td th:text="*{password}" id="password">123456</td>
                <td th:text="*{email}" id="email">[email protected]</td>
                <td><a th:href="'/index/'+*{id}">修改</a>
                    |
                    <a th:href="'/index/delete/'+*{id}">删除</a></td>
            </tr>
            </tbody>

        </table>
    </div>
</body>
</html>

三、测试

  @Test
    public void getPaasword() {

        String password=new BCryptPasswordEncoder(4).encode("123");
        System.out.println("加密|"+password+"|");
    }

由于Security开启了BCrypt加密,所以需要自己搞一个加密后的密码

我自己的数据库:

首先登陆(localhost/tologin)

假如账号错误会回到登录页

假如使用ROLE_ADMIN账号登录

页面中有一个"去管理员页面",只有在管理员登录时显示,并且也只有管理员才能跳转

四、总结

很多地方我自己都还没明白,只是自己用来记录学习,也可以给大家做参考  ,最重要的就是USer和security的配置类,需要重写security的接口方法!

假如有误,请指正!

猜你喜欢

转载自blog.csdn.net/java_zhaoyu/article/details/83029672