SpringBoot整合SpringSecurity

一、添加依赖

 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.4.4</version>
</dependency>

 

创建数据库表

DROP TABLE IF EXISTS `vhr`.`user`;
CREATE TABLE  `vhr`.`user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL DEFAULT '' COMMENT '登录用户名',
  `password` varchar(255) NOT NULL DEFAULT '' COMMENT '登录密码',
  `enabled` tinyint(1) NOT NULL DEFAULT '0',
  `locked` tinyint(1) NOT NULL DEFAULT '0',
  `name` varchar(32) DEFAULT NULL COMMENT '姓名',
  `userface` varchar(255) DEFAULT NULL COMMENT '用户头像',
  `phone` varchar(11) DEFAULT NULL COMMENT '手机号码',
  `telephone` varchar(16) DEFAULT NULL COMMENT '固定电话',
  `address` varchar(255) DEFAULT NULL COMMENT '联系地址',
  `email` varchar(255) DEFAULT NULL COMMENT '电子邮箱',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`role`;
CREATE TABLE  `vhr`.`role` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nameEn` varchar(45) NOT NULL DEFAULT '',
  `nameCn` varchar(45) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`user_role`;
CREATE TABLE  `vhr`.`user_role` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(10) unsigned NOT NULL DEFAULT '0',
  `rid` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `FK_user_role_1` (`uid`),
  KEY `FK_user_role_2` (`rid`),
  CONSTRAINT `FK_user_role_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`),
  CONSTRAINT `FK_user_role_2` FOREIGN KEY (`rid`) REFERENCES `role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`menu`;
CREATE TABLE  `vhr`.`menu` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `url` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '请求路径规则',
  `path` varchar(64) DEFAULT NULL COMMENT '路由path',
  `component` varchar(64) DEFAULT NULL COMMENT '组件英文名称',
  `name` varchar(64) DEFAULT NULL COMMENT '组件中文名称',
  `iconCls` varchar(64) DEFAULT NULL COMMENT '菜单图标',
  `keepAlive` tinyint(1) NOT NULL DEFAULT '0' COMMENT '菜单切换时是否保活',
  `requireAuth` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否登录后才能访问',
  `pid` int(10) unsigned DEFAULT NULL COMMENT '父菜单Id',
  `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否可用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`menu_role`;
CREATE TABLE  `vhr`.`menu_role` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `mid` int(10) unsigned NOT NULL DEFAULT '0',
  `rid` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `FK_menu_role_1` (`mid`),
  KEY `FK_menu_role_2` (`rid`),
  CONSTRAINT `FK_menu_role_1` FOREIGN KEY (`mid`) REFERENCES `menu` (`id`),
  CONSTRAINT `FK_menu_role_2` FOREIGN KEY (`rid`) REFERENCES `role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

二、启动项目测试

随便添加一个简单接口,网页url访问测试,我这里用的是之前的接口

 

 

默认用户名是user,默认密码在每次启动项目时随机生成  

Using generated security password: 0a98ecc8-779b-4dd7-86c6-1b39f6b77437

 

三、后端代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.4.4</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit-dep</artifactId>
            <version>4.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <!-- alibaba数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!-- 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.4.4</version>
        </dependency>



    </dependencies>

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

</project>

 

package com.example.security.demo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;

//@Component
@Service
public class DemoUserDetailsService implements UserDetailsService {
    private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfigurerAdapter.class);
//    @Resource
//    private Mapper
    @Resource
    private PasswordEncoder passwordEncoder;

//    @Autowired
//    UserMapper userMapper;
//    // 重写loadUserByUsername 方法获得 userdetails  类型用户
//    @Override
//    public UserDetails loadUserByUsername(String username) {
//        SysUser user = userMapper.findByUserName(username);
//        if (user != null) {
//            return user;
//        } else {
//            throw new UsernameNotFoundException("admin: " + username + " do not exist!");
//        }
//    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名查找用户信息(通过Mapper查询用户信息)
        logger.info("============loadUserByUsername========================="+username);
        //根据查找到的用户信息判断用户是否被冻结
//        return new User(username,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));//authorities:权限
        return new User(username,passwordEncoder.encode("123456"),
                true,true,true,true,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));//authorities:权限
    }


//    public SecurityUser(User user) {
//        if (user != null) {
//            this.setUserUuid(user.getUserUuid());
//            this.setUsername(user.getUsername());
//            this.setPassword(user.getPassword());
//            this.setEmail(user.getEmail());
//            this.setTelephone(user.getTelephone());
//            this.setRole(user.getRole());
//            this.setImage(user.getImage());
//            this.setLastIp(user.getLastIp());
//            this.setLastTime(user.getLastTime());
//        }
//    }

//    @Override
//    public Collection<? extends GrantedAuthority> getAuthorities() {
//        Collection<GrantedAuthority> authorities = new ArrayList<>();
//        String username = this.getUsername();
//        if (username != null) {
//            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(username);
//            authorities.add(authority);
//        }
//        return authorities;
//    }

//    //账户是否未过期,过期无法验证
//    @Override
//    public boolean isAccountNonExpired() {
//        return true;
//    }
//
//    //指定用户是否解锁,锁定的用户无法进行身份验证
//    @Override
//    public boolean isAccountNonLocked() {
//        return true;
//    }
//
//    //指示是否已过期的用户的凭据(密码),过期的凭据防止认证
//    @Override
//    public boolean isCredentialsNonExpired() {
//        return true;
//    }
//
//    //是否可用 ,禁用的用户不能身份验证
//    @Override
//    public boolean isEnabled() {
//        return true;
//    }
}

 

package com.example.security.demo;

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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
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.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
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.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

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

@Configuration
@EnableWebSecurity
public class DemoSecurityConfig extends WebSecurityConfigurerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfigurerAdapter.class);

    @Autowired
    DemoUserDetailsService demoUserDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder(){
//        return NoOpPasswordEncoder.getInstance();
        return new BCryptPasswordEncoder();
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        logger.info("==============configure==================================");
//        super.configure(http);
        http.csrf().disable();
//        http.authorizeRequests() //对请求进行授权
//                .antMatchers("/login").permitAll()
//                .anyRequest() //任何请求
//                .authenticated()//都要进行身份认证
//                .and()
//                .formLogin()//表单登录
//                .loginPage("/login")//登录页面
//                .loginProcessingUrl("/login")
//                .permitAll();//和登录相关的接口都不需要认证即可访问

        http.authorizeRequests().
                antMatchers("/static/**").permitAll().anyRequest().authenticated().
                and().formLogin().loginPage("/login").permitAll().successHandler(loginSuccessHandler()).
                and().logout().permitAll().invalidateHttpSession(true).
                deleteCookies("JSESSIONID").logoutSuccessHandler(logoutSuccessHandler()).
                and().sessionManagement().maximumSessions(10).expiredUrl("/login");

    }

    //======================================================================

    /**
     * 配置忽略的静态文件,不加的话,登录之前页面的css,js不能正常使用,得登录之后才能正常.
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 忽略URL
        web.ignoring().antMatchers("/**/*.js", "/lang/*.json", "/**/*.css", "/**/*.js", "/**/*.map", "/**/*.html",
                "/**/*.png");
    }

    @Bean
    public LogoutSuccessHandler logoutSuccessHandler() { //登出处理
        return new LogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {

            }
//            @Override
//            public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
//                try {
//                    SecurityUser user = (SecurityUser) authentication.getPrincipal();
////                    logger.info("USER : " + user.getUsername() + " LOGOUT SUCCESS !  ");
//                } catch (Exception e) {
////                    logger.info("LOGOUT EXCEPTION , e : " + e.getMessage());
//                }
//                httpServletResponse.sendRedirect("/login");
//            }
        };
    }

    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler loginSuccessHandler() { //登入处理
        return new SavedRequestAwareAuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                User userDetails = (User) authentication.getPrincipal();
                logger.info("USER : " + userDetails.getUsername() + " LOGIN SUCCESS !  ");
                super.onAuthenticationSuccess(request, response, authentication);
            }
        };
    }

//    @Bean
//    UserDetailsService demoUserDetailsService() {
//        return new DemoUserDetailsService();
//    }

    @Bean
    public UserDetailsService userDetailsService() {    //用户登录实现

//        return new DemoUserDetailsService();
        return new UserDetailsService() {
            //            @Override
//            public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//                return null;
//            }
//            @Autowired
//            private UserRepository userRepository;
            @Resource
            private PasswordEncoder passwordEncoder;

            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                logger.info("=-======loadUserByUsername======-=-========d================"+username);
//                User user = userRepository.findByUsername(s);
//                if (user == null) throw new UsernameNotFoundException("Username " + s + " not found");
//                return new SecurityUser(user);
                return new User(username,passwordEncoder.encode("123456"),
                        true,true,true,true,
                        AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
            }
        };
    }

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

 

package com.example.controller;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Controller
public class LoginController {

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login() {
        System.out.println("--------/login------------");
        return "/login";
    }

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

//    public User getUser() { //为了session从获取用户信息,可以配置如下
//        User user = new User();
//        SecurityContext ctx = SecurityContextHolder.getContext();
//        Authentication auth = ctx.getAuthentication();
//        if (auth.getPrincipal() instanceof UserDetails) user = (User) auth.getPrincipal();
//        return user;
//    }

    public HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

}

 

package com.example.demo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//@SpringBootApplication(scanBasePackages = {"com.example.controller","com.example.service"})
@SpringBootApplication(scanBasePackages = {"com.example"})
@MapperScan("com.example.mapper")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

 

四、前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<h1>登录页面</h1>
<form action="/login" method="post">
    用户名 : <input type="text" name="username"/>
    密码 : <input type="password" name="password"/>
    <input type="submit" value="登录">
</form>
</body>
</html>

 

posted @ 2021-04-04 11:13  残星  阅读(253)  评论(0编辑  收藏  举报