这个只是自己写的一个小demo,可能不适用所有人!
1.首先spingsecurity登录所需要的User类型必须要是UserDetails
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Userlogin implements UserDetails,GrantedAuthority {
String username;
String userpassword;
String role;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
ArrayList<GrantedAuthority> list = new ArrayList();
GrantedAuthority authority = new GrantedAuthority() {
@Override
public String getAuthority() {
return role;
}
};
list.add(authority);
return list;
}
@Override
public String getPassword() {
return userpassword;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
// 密码是否过期
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getAuthority() {
return this.role;
}
}
2.GrantedAuthority 这个接口一般不是加在这里的,但是因为是个小demo就无所谓了。
其中Collection<? extends GrantedAuthority>这个集合是要存放的这个用户所拥有的权限集合(可以理解因为一个项目里一个用户会有多个权限)
写完实体类到service
public interface UserService extends UserDetailsService {
Userlogin queryUserByName(String username);
}
实现类
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserloginMapper userloginMapper;
@Override
public Userlogin queryUserByName(String username) {
Userlogin userlogin = userloginMapper.queryUserByName(username);
if (userlogin == null) {
return null;
} else {
return userlogin;
}
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Userlogin userlogin = userloginMapper.queryUserByName(username);
if (userlogin==null) {
throw new UsernameNotFoundException("用户名不存在");
}
return userlogin;
}
}
Dao使用的是mybatis这里就不说了,因为不是重点
config,重点!
@Configuration
@EnableWebSecurity
public class securityConfig {
@Autowired
UserService userService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
System.out.println("=================securityFilterChain==================");
http.authorizeRequests()
.antMatchers("/vip1*").hasRole("vip1")
.antMatchers("/vip2*").hasRole("vip2")
.and()
.csrf().disable()
.formLogin()
.loginPage("/index")
.permitAll()
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/dashboard")
.loginProcessingUrl("/dologin")
.permitAll();
return http.build();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
return http.build();
}
@Bean
AuthenticationManager authenticationManager(HttpSecurity httpSecurity) throws Exception {
System.out.println("=================authenticationManager==================");
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userService)
.passwordEncoder(new MyPasswordEncoder())
.and()
.build();
return authenticationManager;
}
}
mypasswordencoder
@Component
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(rawPassword.toString());
}
}
到这里基本配置就完成了
注意: .usernameParameter("username") form表单的变量注意是否一致! ( 默认的当我没说 )
.passwordParameter("password")
.defaultSuccessUrl("/dashboard") 表示的是登录成功后跳转的页面
.loginProcessingUrl("/dologin")
表示springsecurity需要拦截什么请求,并且执行自己写的springsecurity登录接口
到这里时我就发现其实controller只需要配置最简单的页面跳转就可以了
controller
@Controller
public class securityController {
@RequestMapping("/index")
public String tologin(){
return "index";
}
// @RequestMapping("/login")
@ResponseBody
// public String securitylogin(HttpServletRequest request) {
// System.out.printf("luguo....");
// return "dashboard";
// }
@RequestMapping("/dashboard")
public String login(){
return "dashboard";
}
@RequestMapping("/list")
public String list(){
return "list";
}
@Controller
public class vipController {
@RequestMapping("/vip{v}")
public String vip(@PathVariable("v") Integer v) {
return "vip" + v;
}
}
登陆页
<body class="text-center">
<form class="form-signin" action="/dologin" method="post">
<!-- <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">-->
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}"></h1>
<p style="color: red" th:if="${not #strings.isEmpty(msg)}" th:text="${msg}"></p>
<label class="sr-only" th:text="#{login.Username}"></label>
<input type="text" name="username" class="form-control" th:placeholder="#{login.Username}" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}"></label>
<input type="password" name="password" class="form-control" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" th:text="#{login.remember}">
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.sign}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2023-2024</p>
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
</form>
</body>
差点忘了, role 必须要是ROLE_ 开头的
最后祝大家不要像我一样卡在这里 T.T