posts - 609,  comments - 13,  views - 64万
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

SecurityConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.jay.SpringBootStudy8.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
 
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)//方法授权
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //用数据库查询的话,就不需要在这里模拟用户了
//    @Bean
//    public UserDetailsService userDetailsService(){
//        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//        manager.createUser(User.withUsername("user2").password("123456").authorities("add","delete","update").roles("vip1").build());
//        manager.createUser(User.withUsername("user3").password("123456").authorities("add","delete","update").roles("vip2").build());
//        return  manager;
//    }
 
    //密码编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    //认证
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        super.configure(auth);
    //BCryptPasswordEncoder 加密方式,用户名admin、密码123456,可以and()连接多个
//        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
//                .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1")
//                .and()
//                .withUser("user1").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2")
//        ;
//    }
 
    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //Security 创建 Session,使用Session保持会话,如果使用 jwt Token,则可以设置成STATELESS,不生成也不是用Session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
        //使用方法授权,不需要下面的web授权配置
        //功能页只有具有权限的人才能访问
//        http.authorizeRequests()
//                .antMatchers("/level1").hasRole("vip1")
//                .antMatchers("/level2").hasRole("vip2")
//                .antMatchers("/level3").authenticated()
//                .anyRequest().permitAll();
 
        //禁用csrf跨站
//        <!--加上后不用禁用csrf-->
//    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
//        http.csrf().disable();
 
        //开启登录,定制登录页,自定义请求参数名 和 登录请求地址。
        //如果不自定义登录请求地址,那登录form的action需要是loginPage指定的地址 /userLogin
        http.formLogin().loginPage("/userLogin")
                .usernameParameter("name")
                .passwordParameter("pwd")
                .loginProcessingUrl("/userLogin")
                .successForwardUrl("/level1")
        ;
        //记住我,自定义请求参数
        http.rememberMe().rememberMeParameter("remember");
        //注销、删除cookie、清除session、跳转登录页
        http.logout().deleteCookies("remove").invalidateHttpSession(true).logoutSuccessUrl("/userLogin");
    }
}

SpringDataUserDetailsService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.jay.SpringBootStudy8.config;
 
import com.jay.SpringBootStudy8.pojo.Permission;
import com.jay.SpringBootStudy8.pojo.Role;
import com.jay.SpringBootStudy8.pojo.SysUser;
import com.jay.SpringBootStudy8.service.PermissionService;
import com.jay.SpringBootStudy8.service.RoleService;
import com.jay.SpringBootStudy8.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
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.Service;
 
import java.util.List;
import java.util.stream.Collectors;
 
@Service
public class SpringDataUserDetailsService implements UserDetailsService {
 
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;
 
    //根据账户查询用户
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        System.out.println("userName:" + s);
        //连接数据库 123456 md5密码 efd9d1b8bfb00e8e3647990f7d74d1d8,BCrypt密码 $2a$10$bobysVYApzaZF2RhNcIQp.qum8V1e9jg5jkqStlRKkfXkB0y4P5AC
        SysUser user = sysUserService.getModelByUserName(s);
        if (user != null) {
            List<Role> roles = roleService.getAllByUserId(user.getId());
            List<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());
            List<Integer> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList());
            List<Permission> permissions = permissionService.getAllByRoleIds(roleIds);
            List<String> permissionCodes = permissions.stream().map(Permission::getCode).collect(Collectors.toList());
            User.UserBuilder builder = User.withUsername(user.getUserName()).password(user.getPwd());
            builder.authorities(permissionCodes.toArray(new String[0]));
//            builder.roles(roleNames.toArray(new String[0]));//roles会替换authorities的赋值
            UserDetails userDetails = builder.build();
            return userDetails;
        }
        return null;
    }
}

 Controller》Action

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RequestMapping("/level1")
    @PreAuthorize("hasAuthority('users:mgr')")//方法授权,方法执行前校验,建议使用
    public String level1(Model model) {
        //得到当前认证通过的用户身份,用户的信息都在这里存着
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();//用户权限
        Object credentials = authentication.getCredentials();//用户凭证
        Object details = authentication.getDetails();//用户详细信息
        Object principal = authentication.getPrincipal();//用户身份
        UserDetails userDetails = (UserDetails) principal;
        String userName = userDetails.getUsername();
        model.addAttribute("userName",userName);
        return "views/level1/1";
    }

 前端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html lang="en_US" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>login</title>
</head>
<body>
<h1>login</h1>
<a th:href="@{/logout}">注销</a>
<a th:href="@{/userLogin}">login</a>
<p th:text="${msg}" style="color: red;"></p>
<form method="post" th:action="@{/userLogin}">
    <!--加上后不用禁用csrf-->
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    name:<input type="text" name="name"/>
    <br/>
    pwd:<input type="password" name="pwd"/>
    <br/>
    <input type="checkbox" name="remember"/>Remember Me
    <br/>
    <button type="submit">submit</button>
</form>
</body>
</html>

视频:https://www.bilibili.com/video/BV1VE411h7aL?p=25

posted on   邢帅杰  阅读(251)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示