SpringSecurity在Springboot中的使用(二)

前情提要:SpringSecurity在Springboot中的使用(一)

本文源码:demo2
与上一个案例相比,本次案例实现了注册功能,和通过查询数据库的用户实现登录功能。

整合Springboot

新建一个springboot项目,其中的pom.xml如下配置:

<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.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>

首先建立一个数据库,取名随意,我取的是demo。

application.properties配置

spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# jpa
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

创建实体类

User.java

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String username;
    private String password;
    private String role = "ROLE_USER";

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

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

    public String getRole() {
        return role;
    }

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

dao层

UserDao.java

public interface UserDao extends JpaRepository<User, Integer> {

    User findByUsername(String username);
}

service层

UserService.java

public interface UserService {

    void register(User user);

    User findByUsername(String username);
}

UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {

    @Resource(name = "userDao")
    private UserDao userDao;

    @Override
    public void register(User user) {
        encryptPassword(user);
        userDao.save(user);
    }

    @Override
    public User findByUsername(String username) {
        return userDao.findByUsername(username);
    }

    /**
     * 加密密码
     */
    private void encryptPassword(User userEntity){
        String password = userEntity.getPassword();
        password = new BCryptPasswordEncoder().encode(password);
        userEntity.setPassword(password);
    }

}

Controller层实现请求映射

@Controller
public class HelloController {

    @Resource(name = "userServiceImpl")
    private UserService userService;

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

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

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

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

    @PostMapping("/register")
    public String register2(User user) {
        User u = userService.findByUsername(user.getUsername());
        if (u == null) {
            userService.register(user);
            return "redirect:/register?success";
        }
        return "redirect:/register?error";
    }
}

实现映射的页面

  • src/main/resources/templates/index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页title>
head>
<body>
<h1>欢迎使用Spring Securityh1>
<p>点击<a href="/hello">这里a>打个招呼吧p>
body>
html>
  • src/main/resources/templates/hello.html

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>欢迎title>
head>
<body>
<h1>hello worldh1>
<form th:action="@{/logout}" method="post">
    <input type="submit" value="注销"/>
form>
body>
html>
  • src/main/resources/templates/login.html

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录title>
head>
<body>
<h1>欢迎用户登录h1>
<div th:if="${param.error}">用户名或密码错误div>
<form th:action="@{/login}" method="post" autocomplete="off">
    <table>
        <tr>
            <td><label for="username">用户名label>td>
            <td><input type="text" id="username" name="username">td>
        tr>
        <tr>
            <td><label for="password">密码label>td>
            <td><input type="password" id="password" name="password">td>
        tr>
        <tr>
            <td><input type="submit" value="提交">td>
            <td><input type="button" value="注册" onclick="register()">td>
        tr>
    table>
form>
body>

<script>
    function register() {
        window.location.href = 'http://localhost:8080/register';
    }
script>
html>
  • src/main/resources/templates/register.html

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>注册title>
head>
<body>
<h1>新用户注册h1>
<form th:action="@{/register}" method="post" autocomplete="off">
    <table>
        <tr>
            <td><label for="username">用户名label>td>
            <td><input type="text" id="username" name="username">td>
        tr>
        <tr>
            <td><label for="password">密码label>td>
            <td><input type="password" id="password" name="password">td>
        tr>
        <tr>
            <td><input type="submit" value="提交">td>
            <td><input type="button" value="登录" onclick="toLogin()">td>
        tr>
    table>
form>
body>

<script>
    function toLogin() {
        window.location.href = "http://localhost:8080/login";
    }
script>
<script th:inline="javascript">
    var msgError = /*[[${param.error}]]*/ 'haha';
    var msgSuccess = /*[[${param.success}]]*/ 'haha';
    if (msgError != null) {
        alert('注册失败,该用户名已存在');
    }
    if (msgSuccess) {
        alert('注册成功,您现在可以登录');
    }
script>
html>

Spring Security配置

实现UserDetailsService接口,重写loadUserByUsername()方法。
AnyUserDetailsService.java

@Service
public class AnyUserDetailsService implements UserDetailsService {

    private final UserService userService;

    @Autowired
    AnyUserDetailsService(UserService userService){
        this.userService = userService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        com.example.demo.entity.User userEntity = userService.findByUsername(username);
        if (userEntity == null){
            throw new UsernameNotFoundException("用户不存在!");
        }
        List<SimpleGrantedAuthority> simpleGrantedAuthorities = createAuthorities(userEntity.getRole());
        return new User(userEntity.getUsername(), userEntity.getPassword(), simpleGrantedAuthorities);
    }

    /**
     * 权限字符串转化
     *
     * 如 "USER,ADMIN" -> SimpleGrantedAuthority("USER") + SimpleGrantedAuthority("ADMIN")
     *
     * @param roleStr 权限字符串
     */
    private List<SimpleGrantedAuthority> createAuthorities(String roleStr){
        String[] roles = roleStr.split(",");
        List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
        for (String role : roles) {
            simpleGrantedAuthorities.add(new SimpleGrantedAuthority(role));
        }
        return simpleGrantedAuthorities;
    }

}

WebSecurityConfig.java

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private AnyUserDetailsService anyUserDetailsService;

    @Autowired
    public void setAnyUserDetailsService(AnyUserDetailsService anyUserDetailsService){
        this.anyUserDetailsService = anyUserDetailsService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .antMatchers("/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception{
        builder.userDetailsService(anyUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
}

启动项目,来看一下效果吧
启动项目后,访问http://localhost:8080/:
SpringSecurity在Springboot中的使用(二)_第1张图片
点击超链接"这里"访问/hello,由于没有登录,页面将被重定向到/login页面:
SpringSecurity在Springboot中的使用(二)_第2张图片
我们现在还没有注册,先注册一个,点击注册按钮,跳转到注册页面:
SpringSecurity在Springboot中的使用(二)_第3张图片
随便注册一个用户,点击提交,会有弹出框提示注册成功,然后我们点击登录按钮进行登录,登录成功会出现欢迎界面:
SpringSecurity在Springboot中的使用(二)_第4张图片

你可能感兴趣的:(security,工作笔记)