Spring Security —07—传统web开发认证总结案例

7.1 新建项目

7.2 pom.xml引入依赖

 <!--Thymeleaf-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-thymeleaf</artifactId>
 </dependency><!--SpringBoot security-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-security</artifactId>
 </dependency><!--页面上获取用户信息-->
 <dependency>
     <groupId>org.thymeleaf.extras</groupId>
     <artifactId>thymeleaf-extras-springsecurity5</artifactId>
     <version>3.0.4.RELEASE</version>
 </dependency><!--引入数据源-->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.2.7</version>
 </dependency><!--引入mysql-->
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.38</version>
 </dependency><!--引入mybatis-->
 <dependency>
     <groupId>org.mybatis.spring.boot</groupId>
     <artifactId>mybatis-spring-boot-starter</artifactId>
     <version>2.2.0</version>
 </dependency>

7.3 application.properties添加配置

 # 配置Thymeleaf
 spring.thymeleaf.cache=false
 spring.thymeleaf.prefix=classpath:/templates/
 spring.thymeleaf.suffix=.html
 spring.thymeleaf.encoding=UTF-8
 spring.thymeleaf.mode=HTML
 # datasource:类型、驱动名、用户名、密码
 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 spring.datasource.url=jdbc:mysql://localhost:3306/security?characterEncoding=UTF-8&useSSL=false
 spring.datasource.username=root
 spring.datasource.password=root
 # mybatis配置mapper文件的位置和别名设置
 # 注意mapper目录(包)新建时必须使用"/",而不是.
 mybatis.mapper-locations=classpath:com/study/mapper/*.xml
 mybatis.type-aliases-package=com.study.entity
 # log:为了显示mybatis运行SQL语句
 logging.level.com.study=debug

7.4 创建实体类entity

User

 package com.study.entity;import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;import java.util.*;/**
  * @ClassName User
  * @Description TODO
  * @Date 2022/8/7 15:16
  * @Version 1.0
  */
 public class User implements UserDetails {
     private Integer id;
     private String username;
     private String password;
     private Boolean enabled;
     private Boolean accountNonExpired;
     private Boolean accountNonLocked;
     private Boolean credentialsNonExpired;
     private List<Role> roles = new ArrayList<>();//关系属性,用来存储当前用户所有角色信息//返回权限信息
     @Override
     public Collection<? extends GrantedAuthority> getAuthorities() {
         Set<SimpleGrantedAuthority> authorities = new HashSet<>();
         roles.forEach(role -> {
             SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(role.getName());
             authorities.add(simpleGrantedAuthority);
         });
         return authorities;
     }@Override
     public String getPassword() {
         return password;
     }public void setPassword(String password) {
         this.password = password;
     }@Override
     public String getUsername() {
         return username;
     }public void setUsername(String username) {
         this.username = username;
     }@Override
     public boolean isAccountNonExpired() {
         return accountNonLocked;
     }@Override
     public boolean isAccountNonLocked() {
         return accountNonLocked;
     }@Override
     public boolean isCredentialsNonExpired() {
         return credentialsNonExpired;
     }@Override
     public boolean isEnabled() {
         return enabled;
     }public Integer getId() {
         return id;
     }public void setId(Integer id) {
         this.id = id;
     }public Boolean getEnabled() {
         return enabled;
     }public void setEnabled(Boolean enabled) {
         this.enabled = enabled;
     }public Boolean getAccountNonExpired() {
         return accountNonExpired;
     }public void setAccountNonExpired(Boolean accountNonExpired) {
         this.accountNonExpired = accountNonExpired;
     }public Boolean getAccountNonLocked() {
         return accountNonLocked;
     }public void setAccountNonLocked(Boolean accountNonLocked) {
         this.accountNonLocked = accountNonLocked;
     }public Boolean getCredentialsNonExpired() {
         return credentialsNonExpired;
     }public void setCredentialsNonExpired(Boolean credentialsNonExpired) {
         this.credentialsNonExpired = credentialsNonExpired;
     }public List<Role> getRoles() {
         return roles;
     }public void setRoles(List<Role> roles) {
         this.roles = roles;
     }
 }

Role

 package com.study.entity;/**
  * @ClassName Role
  * @Description TODO
  * @Date 2022/8/7 15:17
  * @Version 1.0
  */
 public class Role {
     private Integer id;
     private String name;
     private String nameZh;public Integer getId() {
         return id;
     }public void setId(Integer id) {
         this.id = id;
     }public String getName() {
         return name;
     }public void setName(String name) {
         this.name = name;
     }public String getNameZh() {
         return nameZh;
     }public void setNameZh(String nameZh) {
         this.nameZh = nameZh;
     }
 }

7.5 创建UserDao

 package com.study.dao;import com.study.entity.Role;
 import com.study.entity.User;
 import org.apache.ibatis.annotations.Mapper;import java.util.List;/**
  * @ClassName UserDao
  * @Description TODO
  * @Date 2022/8/7 15:19
  * @Version 1.0
  */
 @Mapper
 public interface UserDao {
     /**
      * 根据用户名查找用户
      *
      * @param username
      * @return
      */
     User loadUserByUsername(String username);/**
      * 根据用户id查询一个角色,注意一个用户可能不止一种角色
      *
      * @param uid
      * @return
      */
     List<Role> getRolesByUid(Integer uid);
 }

7.6 创建UserDAOMapper.xml

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.study.dao.UserDao">
     <!--loadUserByUsername-->
     <select id="loadUserByUsername" resultType="User">
         select id,
                username,
                password,
                enabled,
                accountNonExpired,
                accountNonLocked,
                credentialsNonExpired
         from user
         where username = #{username}
     </select><!--getRolesByUid
         需要将角色表和用户-角色表进行关联查询,查询条件为role.id=user_role.uid
         其中,uid是外界传入的参数
     -->
     <select id="getRolesByUid" resultType="Role">
         select r.id,
                r.name,
                r.name_zh nameZh
         from role r,
              user_role ur
         where r.id = ur.rid
           and ur.uid = #{uid}
     </select>
 </mapper>

7.7 创建MyUserDetailsService

 package com.study.service;import com.study.dao.UserDao;
 import com.study.entity.User;
 import org.springframework.beans.factory.annotation.Autowired;
 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.Service;
 import org.springframework.util.ObjectUtils;/**
  * @ClassName MyUserDetailsService
  * @Description TODO
  * @Date 2022/8/7 15:15
  * @Version 1.0
  */
 @Service
 public class MyUserDetailsService implements UserDetailsService {
     private final UserDao userDao;@Autowired
     public MyUserDetailsService(UserDao userDao) {
         this.userDao = userDao;
     }@Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
         User user = userDao.loadUserByUsername(username);
         if (ObjectUtils.isEmpty(user))
             throw new UsernameNotFoundException("用户不存在");
         user.setRoles(userDao.getRolesByUid(user.getId()));
         return user;
     }
 }

7.8 编写html

login.html

 <!DOCTYPE html>
 <html lang="en" xmlns:th="http://www.thymeleaf.org">
 <head>
     <meta charset="UTF-8">
     <title>登录页面</title>
 </head>
 <body>
 <h1>用户登录</h1>
 <form method="post" th:action="@{/doLogin}">
     用户名:<input name="uname" type="text"><br>
     密码:<input name="pwd" type="password"><br>
     <input type="submit" value="登录">
 </form>
 <h2>
     <!--    <div th:text="${SPRING_SECURITY_LAST_EXCEPTION}"></div>--><!--request作用域:forward跳转-->
     <div th:text="${session.SPRING_SECURITY_LAST_EXCEPTION}"></div><!--session作用域:redirect跳转-->
 </h2>
 </body>
 </html>

index.html

 <!DOCTYPE html>
 <html lang="en" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
       xmlns:th="https://www.thymeleaf.org">
 <head>
     <meta charset="UTF-8">
     <title>系统主页</title>
 </head>
 <body>
 <h1>欢迎<span sec:authentication="principal.username"></span>,进入我的系统!</h1>
 <h3>用户详细信息如下:</h3>
 <ul>
     <li sec:authentication="principal.username"></li>
     <li sec:authentication="principal.authorities"></li>
     <li sec:authentication="principal.accountNonExpired"></li>
     <li sec:authentication="principal.accountNonLocked"></li>
     <li sec:authentication="principal.credentialsNonExpired"></li>
 </ul>
 <br>
 <a th:href="@{/logout}">退出登录</a>
 </body>
 </html>

7.9 编写MvcConfigurer

 package com.study.config;import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/**
  * @ClassName MvcConfigurer
  * @Description 对SpringMVC进行自定义配置
  * @Date 2022/8/7 14:20
  * @Version 1.0
  */
 @Configuration
 public class MvcConfigurer implements WebMvcConfigurer {@Override
     public void addViewControllers(ViewControllerRegistry registry) {
         //addViewController: forward跳转
         registry.addViewController("/login.html").setViewName("login");
         registry.addViewController("/index.html").setViewName("index");
     }
 }

7.10 编写SecurityConfigurer

 package com.study.config;import com.study.service.MyUserDetailsService;
 import org.springframework.beans.factory.annotation.Autowired;
 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.configuration.WebSecurityConfigurerAdapter;/**
  * @ClassName SecurityConfiger
  * @Description 自定义security相关配置
  * @Date 2022/8/7 14:35
  * @Version 1.0
  */
 @Configuration
 public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
     //    @Bean
	 //    public UserDetailsService userDetailsService() {
	 //        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
	 //        userDetailsManager.createUser(User.withUsername("root").password("{noop}123456").roles("admin").build());
	 //        return userDetailsManager;
	 //    }
 
 	//自定义数据源注入
     @Autowired
     private MyUserDetailsService myUserDetailsService;
 	//自定义全局配置​AuthenticationManager
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.userDetailsService(myUserDetailsService);
     }@Override
     protected void configure(HttpSecurity http) throws Exception {
         http.authorizeRequests()
                 .mvcMatchers("/login.html").permitAll()
                 .anyRequest().authenticated()
                 .and()
                 .formLogin()
                 .loginPage("/login.html") //指定自定义登录页面
                 .loginProcessingUrl("/doLogin")
                 .usernameParameter("uname")
                 .passwordParameter("pwd")
                 .defaultSuccessUrl("/index.html", true)
                 .failureUrl("/login.html")
                 .and()
                 .logout()
                 .logoutUrl("/logout")
                 .logoutSuccessUrl("/login.html")
                 .and()
                 .csrf().disable();
     }
 }
 

7.11 启动服务测试

(1)登录数据库中含有的用户时,登录成功后显示认证信息:
在这里插入图片描述

(2)登录数据库中不含有的用户时,认证后显示错误信息:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值