通过访问数据库,实现不同用户、不同角色登录系统。
以简单的表结构演示案例。
一 创建数据表
角色表 (role):
用户表 (user):
用户角色关系表(user_role):
二 搭建项目结构
三 编码实现
1)yml配置文件
server:
servlet:
context-path: /zmd
mybatis:
type-aliases-package: com.zmd.pojo # 批量设置别名
mapper-locations: classpath:com/zmd/mapper/*.xml # 设置mapper的路径
configuration:
auto-mapping-behavior: full # 设置全自动映射
use-column-label: true # 设置别名可以做列名
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/ssm?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: root
password: 123456
thymeleaf:
cache: false
suffix: .html
jackson:
# 如果使用字符串星表示用这行格式
date-format: yyyy-MM-dd
# 设置为东八区时间
timezone: GMT+8
# 想要值为2016-01-01
serialization:
write-dates-as-timestamps: false
# 显示SQL语句
logging:
level:
com:
zmd:
mapper: debug
2)实体类(pojo)
user:
@Data
public class User {
private Integer id;
private String name;
private String password;
private List<Role> roles=new ArrayList<>();
}
role:
扫描二维码关注公众号,回复:
16661253 查看本文章
@Data
public class Role {
private Integer id;
private String name;
private List<User> users = new ArrayList<User>();
}
3)mapper
<?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.zmd.mapper.UserMapper">
<select id="getUser" resultMap="roleList">
select r.id, r.name,u.id uid,u.name uname,u.password from role r left join user_role ur
on ur.rid=r.id
LEFT JOIN user u
on u.id=ur.uid
where u.name=#{name}
</select>
<!--根据用户的id查询这个用户的所有的角色-->
<resultMap id="roleList" type="user" autoMapping="true">
<id column="uid" property="id"></id>
<result property="name" column="uname"></result>
<collection property="roles" ofType="role" autoMapping="true">
<id column="id" property="id"></id>
</collection>
</resultMap>
</mapper>
在启动类中配置扫描:
@SpringBootApplication
@MapperScan("com.zmd.mapper")
public class Security1902Application {
public static void main(String[] args) {
SpringApplication.run(Security1902Application.class, args);
}
4)service业务
通过重写方法,从当前登录账号对应的数据库数据中获取到账号角色等信息。
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Collection<GrantedAuthority> authorities = new ArrayList<>();
User user = userMapper.getUser(username);
System.out.println("service来了");
if (user == null) {
System.out.println("该用户不存在");
} else {
List<Role> roles = user.getRoles();
for (Role r : roles) {
System.out.println("角色:"+r.getName());
authorities.add(new SimpleGrantedAuthority(r.getName()));
}
org.springframework.security.core.userdetails.User u = new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(), authorities);
System.out.println("u:"+u);
return u;
}
return null;
}
}
5)配置类WebSecurityConfig
@Configuration
@EnableWebSecurity //启动安全框架
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启注解级别方法权限控制
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin() //指定支持基于表单的身份验证
.loginPage("/login") //默认的登录路径
.loginProcessingUrl("/loginCheck")//登录页面提交的路径,需要和页面的路径保持一致
.defaultSuccessUrl("/logSuccess")//登录成功后跳转的路径
.failureUrl("/error2")//登录失败后跳转的路径
.usernameParameter("username")//获取页面的配置的用户名,和页面的值保持一致
.passwordParameter("password")
.permitAll()//路径不设权限
.and()
.csrf().disable();//阻止跨域请求伪造攻击
}
//用于对比密码
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
});
}
//静态请求要放行
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/webjars/**").antMatchers("/static/**");
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
6)controller
@Controller
public class MyController {
@RequestMapping("/login")
public String login(){
System.out.println("这是login。。。");
return "login";
}
@RequestMapping("/logSuccess")
public String logSuccess(){
System.out.println("登录成功");
return "index";
}
@RequestMapping("/error2")
@PreAuthorize("hasAnyAuthority('admin','user')")
public String error111(){
return "error1";
}
}
7)登录页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录界面</title>
<script type="text/javascript" th:src="@{/webjars/jquery/3.3.1/jquery.js}"></script>
<script type="text/javascript" th:src="@{/webjars/layui/2.5.6/layui.js}" ></script>
<link rel="stylesheet" th:href="@{/webjars/layui/2.5.6/css/layui.css}" />
<style type="text/css">
.container{
width: 420px;
height: 320px;
min-height: 320px;
max-height: 320px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
padding: 20px;
z-index: 130;
border-radius: 8px;
background-color: #fff;
box-shadow: 0 3px 18px rgba(100, 0, 0, .5);
font-size: 16px;
}
.close{
background-color: white;
border: none;
font-size: 18px;
margin-left: 410px;
margin-top: -10px;
}
.layui-input{
border-radius: 5px;
width: 300px;
height: 40px;
font-size: 15px;
}
.layui-form-item{
margin-left: -20px;
}
#logoid{
margin-top: -16px;
padding-left:150px;
padding-bottom: 15px;
}
.layui-btn{
margin-left: -50px;
border-radius: 5px;
width: 350px;
height: 40px;
font-size: 15px;
}
.verity{
width: 120px;
}
.font-set{
font-size: 13px;
text-decoration: none;
margin-left: 120px;
}
a:hover{
text-decoration: underline;
}
</style>
</head>
<body>
<!-- 注意此处提交的路径-->
<form class="layui-form" th:action="@{/loginCheck}" method="post">
<div class="container">
<button class="close" title="关闭">X</button>
<div class="layui-form-mid layui-word-aux">
<img id="logoid" src="" height="35">
</div>
<div class="layui-form-item">
<label class="layui-form-label">用户名</label>
<div class="layui-input-block">
<input type="text" name="username" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密 码</label>
<div class="layui-input-inline">
<input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
</div>
<!-- <div class="layui-form-mid layui-word-aux">辅助文字</div> -->
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formDemo">登陆</button>
</div>
<div class="layui-input-block">
<button type="reset" class="layui-btn layui-btn-warm">重置</button>
</div>
</div>
<a href="" class="font-set">忘记密码?</a> <a href="" class="font-set">立即注册</a>
</div>
</form>
</body>
</html>
四 运行测试
1)错误账号密码登录:
登录失败,不会进行跳转。
2)登录成功
观察控制台:
小结
通过上述步骤,实现了用户登录。
该用户的账号和密码必须匹配数据表中数据,并且可以成功获取到该账号对应的角色,
以方便后续进行权限的相关处理。
欢迎留言评论,交流学习。