使用Spring Security实现注册登录

1.文件结构

文件结构.png

2.依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.dfyang</groupId>
    <artifactId>springsecurity</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springsecurity</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.14.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>
        <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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

</project>

3.aplication.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncording=utf-8&useSSL=true
    username: root
    password: 151310
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    show-sql: true

4.要用到的3个页面,用的是Thymeleaf

首页
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>首页</title>
</head>
<body>
    首页
</body>
</html>
登录页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>登录</title>
</head>
<body>
    <h1>登录</h1>
    <form action="/doLogin" method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input name="username" type="text" /></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input name="password" type="password" /></td>
            </tr>
        </table>
        <button type="submit">提交</button>
    </form>
</body>
</html>
注册页面
<!DOCTYPE html>
<html xmlns="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>注册</title>
</head>
<body>
    <h1>注册</h1>
    <form action="/doRegister" method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input name="username" type="text" /></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input name="password" type="password" /></td>
            </tr>
        </table>
        <button type="submit">提交</button>
    </form>
</body>
</html>

5.实体类

package com.dfyang.springsecurity.entity;

import lombok.Data;

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

@Data
@Entity
public class User {
    @Id
    private String username;

    private String password;
}

6.dao层

package com.dfyang.springsecurity.dao;

import com.dfyang.springsecurity.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserJpa extends JpaRepository<User, String> {
}

7.service层——由于只完成登录注册,只写了两个简单的方法

package com.dfyang.springsecurity.service;

import com.dfyang.springsecurity.entity.User;

public interface UserService {
    User findUserByUsername(String username);

    User addUser(User user);
}
package com.dfyang.springsecurity.service.impl;

import com.dfyang.springsecurity.dao.UserJpa;
import com.dfyang.springsecurity.entity.User;
import com.dfyang.springsecurity.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private PasswordEncoder passwordEncoder; //security提供的加密接口,先写着,等会配置

    @Autowired
    private UserJpa userJpa;

    @Override
    public User findUserByUsername(String username) {
        User user = userJpa.findOne(username);
        return user;
    }

    @Override
    public User addUser(User user) {
        if (user.getUsername() != null && user.getPassword() != null){
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            userJpa.save(user);
        }
        else
            user = null;
        return user;
    }
}

8.controller层

用于返回页面
package com.dfyang.springsecurity.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {

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

    @GetMapping("/login")
    public String login(){
        return "loginPage";
    }

    @GetMapping("/register")
    public String register() {
        return "registerPage";
    }
}
用于处理请求
package com.dfyang.springsecurity.controller;

import com.dfyang.springsecurity.entity.User;
import com.dfyang.springsecurity.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/doRegister")
    public String register(User user) {
        userService.addUser(user);
        return user == null ? "注册失败" : "注册成功";
    }
}

9.security配置类,这是关键

package com.dfyang.springsecurity.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //这里配置PasswordEncoder,BCryptPasswordEncoder是security提供的PasswordEncorder的一个实现类
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();    
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic()     //security提供的登录页面
                .and()
                .authorizeRequests()    //认证请求
                .antMatchers("/register", "/doRegister", "/login", "/doLogin").permitAll()     //除了***能够无认证访问
                .anyRequest().authenticated()    //任何请求都需要认证
                .and()
                .csrf().disable();     //CSRF跨站请求伪造直接关闭
    }
}

10.加载用户登录信息类——通过你登录时输入的账号从数据库进行查找,找到后将信息封装交给security的登录处理机制进行处理

package com.dfyang.springsecurity.security;

import com.dfyang.springsecurity.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
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.stereotype.Component;

@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        com.dfyang.springsecurity.entity.User user = userService.findUserByUsername(s);
        return new User(s, user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

11.接下来使用security提供的登录页面试一下

http://localhost:8080/register

注册页面.png

输出用户名admin,密码123456(随意),提交注册后进入/doRegister进行逻辑处理
注册结果.png
此时数据库多了一条数据
数据.png
接着访问index页面,由于没有在security配置类中antMatchers中加入"/index",所以请求被拦截,要求进行登录,以下就是security提供的登录页面,各浏览器显示可能有所不同

http://localhost:8080/index

访问index.png

输入我们刚才注册的账号,成功访问index页面
index页面.png

12.接下来使用自己写的登录页面试一下

修改security配置类
package com.dfyang.springsecurity.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin()   //使用表单登录页面
                .loginPage("/login")    //登录url
                .loginProcessingUrl("/doLogin")    //登录提交url
                .and()
                .authorizeRequests()
                .antMatchers("/register", "/doRegister", "/login", "/doLogin").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }
}
同样访问index页面

http://localhost:8080/index

访问index页面.png

接下来的都一样,如果出现localhost 将您重定向的次数过多。请检查security配置类antMatchers是否有误
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容