[英]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.