[英]Role based authorization in my Spring Boot project
这是我的 SuccessHandler 类
package com.myproject.configure;
import java.io.IOException;
import java.rmi.AccessException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
@Component
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {
// @Override
// protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//
// String targetUrl = determineTargetUrl(authentication);
//
// System.out.println("Its a Target URL ---" + targetUrl);
// if (response.isCommitted()) {
// return;
// }
// RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
// redirectStrategy.sendRedirect(request, response, targetUrl);
// }
protected String determineTargetUrl(Authentication authentication) {
String url = "/login?error=true";
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
List<String> roles = new ArrayList<String>();
for (GrantedAuthority a : authorities) {
roles.add(a.getAuthority());
}
if (roles.contains("SITE_ADMIN")) {
System.out.println(roles.toString());
url = "/admin/home";
}
else if (roles.contains("SITE_USERS")) {
url = "/users/index";
}
return url;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
String redirectUrl = determineTargetUrl(authentication);
if (redirectUrl == null) {
throw new AccessException(redirectUrl);
}
new DefaultRedirectStrategy().sendRedirect(request, response, redirectUrl);
}
}
这里我定义了两个不同的角色,一个是“ADMIN”,另一个是“USER”
我的用户有两个不同的实体类,角色有另一个。 对于不同的角色,我有两个不同的目的地。 但是当我运行我的应用程序并成功登录时,只有“USER”角色可以看到它的页面,而“ADMIN”角色用户看不到他们的页面。 但是我可以在控制台中看到 admin print 语句。 “这是管理员!!!!!”。 该怎么办 ? 或者我的错误在哪里?
这是我的实体类:
package com.myproject.entities;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "users")
public class Users {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_users")
private int idUsers;
private String userName;
private String password;
@ManyToOne(cascade = CascadeType.ALL)
private UserRole userRole;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "id_users")
List<Recruitment> recruitments = new ArrayList<>();
public Users() {
}
public Users(String userName, String password, UserRole userRole, List<Recruitment> recruitments) {
this.userName = userName;
this.password = password;
this.userRole = userRole;
this.recruitments = recruitments;
}
public int getIdUsers() {
return idUsers;
}
public String getUserName() {
return userName;
}
public String getPassword() {
return password;
}
public UserRole getUserRole() {
return userRole;
}
public List<Recruitment> getRecruitments() {
return recruitments;
}
public void setIdUsers(int idUsers) {
this.idUsers = idUsers;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
public void setUserRole(UserRole userRole) {
this.userRole = userRole;
}
public void setRecruitments(List<Recruitment> recruitments) {
this.recruitments = recruitments;
}
@Override
public String toString() {
return "Users [idUsers=" + idUsers + ", userName=" + userName + ", password=" + password + ", userRole="
+ userRole + ", recruitments=" + recruitments + "]";
}
}
package com.myproject.entities;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "user_role")
public class UserRole {
@Id
@Column(name = "iduser_role")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int idUserRole;
private String roleName;
@OneToMany(mappedBy = "userRole")
private List<Users> users;
public UserRole() {
}
public int getIdUserRole() {
return idUserRole;
}
public String getRoleName() {
return roleName;
}
public List<Users> getUsers() {
return users;
}
public void setIdUserRole(int idUserRole) {
this.idUserRole = idUserRole;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public void setUsers(List<Users> users) {
this.users = users;
}
}
这是我的控制器:
@RequestMapping("/login")
public String login() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
return "login";
}
return "redirect:/login";
}
@RequestMapping("/logout")
public String logout() {
return "login";
}
@GetMapping
public String login(@RequestParam(value = "error", defaultValue = "false") boolean loginError) {
if (loginError) {
return "error-404";
}
return "login";
}
@RequestMapping("/admin/home")
public String loginAdmin(Model model) {
System.out.println("From Admin Controller");
return "/admin/home";
}
@RequestMapping("/user/home")
public String loginUser(Model model) {
System.out.println("From User Controller");
return "/user/home";
}
这是我的 WebSecurityConfiguration 文件:
package com.myproject.configure;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.recruitmentmanagement.service.CustomUserDetailsService;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private CustomLoginSuccessHandler successHandler;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/login","/registration", "/process_registration", "/userhome", "/landing", "/order", "/jobdetails/**").permitAll()
.antMatchers("/user/**").hasAnyAuthority("USER", "ADMIN")
.antMatchers("/admin/**").hasAnyAuthority("ADMIN")
.anyRequest().authenticated()
.and()
.csrf().disable().formLogin()
.loginPage("/login")
.failureUrl("/login?error=true")
.successHandler(successHandler)
.usernameParameter("userName")
.passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login").and()
.exceptionHandling()
.accessDeniedPage("/access-denied");
}
@Bean
public LogoutSuccessHandler logoutSuccessHandler() {
return new CustomLogoutSuccessHandler();
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/webjars/**",
"/css/**",
"/js/**",
"/images/**",
"/node_modules/**",
"/bower_components/**");
}
@Bean
public DaoAuthenticationProvider authProvider() throws Exception {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setPasswordEncoder(passwordEncoder());
authenticationProvider.setUserDetailsService(userDetailsService);
return authenticationProvider;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("WebSecurityConfig -- " + authProvider().toString());
auth.authenticationProvider(authProvider());
}
}
考虑使用官方 Spring Security 模型
所以一切都会为你做的
您可以为某些页面指定角色和权限
好的,首先,您必须扩展 AuthenticationSuccessHandler,并且您的句柄方法应如下所示
@Component
public class CustomSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
String redirectUrl = determineTargetUrl(authentication);
if (redirectUrl == null) {
throw new SomeException();
}
new DefaultRedirectStrategy().sendRedirect(request, response, redirectUrl);
}
}
此时 url 'login?error=true' 是多余的。 您可以安全地从 defineTargeUrl 中删除它,因为您是在 WebSecurityConfig 类中的失败登录 url 中定义的。
有了这个说控制器应该看起来像这样
@Controller
@RequestMapping
public class TestController {
...
}
我看不到您的控制器类的顶部,因此请确保您已获得这两个注释。 定义以下条件时也要小心
hasAnyAuthority("USER", "ADMIN")
和
roleName.contains("ADMIN")
您必须在重定向类中使用“equals”,这可能会导致歧义
实际上,我只获得了 [USER] 作为权限,这是我在打印 authentication.getAuthorities() 时发现的; 来自我的 SuccessHandler 课程。 当我从 WebSecurity 类检查我的 authProvider() 函数时,我的用户权限由我的 CustomUserDetailsService 提供。 我检查了我的 CustomUserDetailsService 类,发现以下内容:
package com.myproject.service;
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 com.recruitmentmanagement.entities.Users;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
UsersService usersService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final Users users = usersService.getUsersByUsers(username);
if (users == null) {
throw new UsernameNotFoundException("User not found !!!");
}
UserDetails userDetails = User.withUsername(users.getUserName()).password(users.getPassword()).authorities("USER").build();
return userDetails;
}
}
然后我更改我的代码,这是我的最终 CustomUserDetailService 类
package com.myproject.service;
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 com.recruitmentmanagement.entities.Users;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
UsersService usersService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final Users users = usersService.getUsersByUsers(username);
if (users == null) {
throw new UsernameNotFoundException("User not found !!!");
}
UserDetails userDetails = User.withUsername(users.getUserName()).password(users.getPassword()).authorities(users.getUserRole().getRoleName()).build();
return userDetails;
}
}
感谢所有试图帮助我的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.