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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>欢迎使用Spring Security</h1>
<p>点击<a href="/hello">这里</a>打个招呼吧</p>
</body>
</html>
  • src/main/resources/templates/hello.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>欢迎</title>
</head>
<body>
<h1>hello world</h1>
<form th:action="@{/logout}" method="post">
    <input type="submit" value="注销"/>
</form>
</body>
</html>
  • src/main/resources/templates/login.html
<!DOCTYPE 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
<!DOCTYPE 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/:
首页
点击超链接"这里"访问/hello,由于没有登录,页面将被重定向到/login页面:
登录
我们现在还没有注册,先注册一个,点击注册按钮,跳转到注册页面:
注册
随便注册一个用户,点击提交,会有弹出框提示注册成功,然后我们点击登录按钮进行登录,登录成功会出现欢迎界面:
欢迎

猜你喜欢

转载自blog.csdn.net/ClassLjx/article/details/87971184