Spring boot - 尝试从 mySQL DB 验证用户 - 需要授予权限的文本表示
Posted
技术标签:
【中文标题】Spring boot - 尝试从 mySQL DB 验证用户 - 需要授予权限的文本表示【英文标题】:Spring boot - Try to authenticate user from mySQL DB - A granted authority textual representation is required 【发布时间】:2019-03-22 13:01:20 【问题描述】:2018-10-17 20:05:37.715 ERROR 15968 --- [nio-8090-exec-3] w.a.UsernamePasswordAuthenticationFilter :尝试对用户进行身份验证时发生内部错误。
org.springframework.security.authentication.InternalAuthenticationServiceException: 需要授权的文本表示
这是我的SecurityConfig:
package com.project.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.crypto.bcrypt.BCryptPasswordEncoder;
@ComponentScan(basePackages= "com.project.*")
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled=true)
@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private MyAppUserDetailsService myAppUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests()
.antMatchers("/app/secure/**").hasAnyRole("ADMIN","USER")
.and().formLogin() //login configuration
.loginPage("/app/login")
.loginProcessingUrl("/app-login")
.usernameParameter("userName")
.passwordParameter("password")
.defaultSuccessUrl("/app/secure/temployee-details")
.and().logout() //logout configuration
.logoutUrl("/app-logout")
.logoutSuccessUrl("/app/login")
.and().exceptionHandling() //exception handling configuration
.accessDeniedPage("/app/error");
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.userDetailsService(myAppUserDetailsService).passwordEncoder(passwordEncoder);
以及UserDetailsService:
package com.project.config;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.project.dao.IUserInfoDAO;
import com.project.entity.UserInfo;
@ComponentScan(basePackages= "com.project.*")
@Service
public class MyAppUserDetailsService implements UserDetailsService
@Autowired
private IUserInfoDAO userInfoDAO;
@Override
public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException
UserInfo activeUserInfo = userInfoDAO.getActiveUser(userName);
GrantedAuthority authority = new SimpleGrantedAuthority(activeUserInfo.getRole());
UserDetails userDetails = (UserDetails)new User(activeUserInfo.getUserName(),
activeUserInfo.getPassword(), Arrays.asList(authority));
return userDetails;
UserInfoDao:
package com.project.dao;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.project.entity.TEmployee;
import com.project.entity.UserInfo;
@ComponentScan(basePackages= "com.project.*")
@Repository
@Transactional
public class UserInfoDAO implements IUserInfoDAO
@PersistenceContext
private EntityManager entityManager;
public UserInfo getActiveUser(String userName)
UserInfo activeUserInfo = new UserInfo();
short enabled = 1;
List<?> list = entityManager.createQuery("SELECT u FROM UserInfo u WHERE userName=?1 and enabled=?2")
.setParameter(1, userName).setParameter(2, enabled).getResultList();
if(!list.isEmpty())
activeUserInfo = (UserInfo)list.get(0);
return activeUserInfo;
@SuppressWarnings("unchecked")
@Override
public List<TEmployee> getAllUserEmployees()
String hql = "FROM TEmployee as t ORDER BY t.employee_id";
return (List<TEmployee>) entityManager.createQuery(hql).getResultList();
我真的不明白为什么我仍然收到 A 授予权限文本表示是必需的。 我已经在我的数据库中的“角色”列中添加了一个适当的角色:ROLE_ADMIN
或ROLE_USER
,这里的一切似乎都很好。
一些日志:
2018-10-17 20:05:29.932 信息 15968 --- [nio-8090-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]:初始化 Spring FrameworkServlet 'dispatcherServlet' 2018-10-17 20:05:29.932 信息 15968 --- [nio-8090-exec-1] os.web.servlet.DispatcherServlet: FrameworkServlet 'dispatcherServlet':初始化开始 2018-10-17 20:05:29.938 信息 15968 --- [nio-8090-exec-1] os.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet':初始化在 6 毫秒内完成 2018-10-17 20:05:37.694 信息 15968 --- [nio-8090-exec-3] o.h.h.i.QueryTranslatorFactoryInitiator:HHH000397:使用 ASTQueryTranslatorFactory 2018-10-17 20:05:37.701 调试 15968 --- [nio-8090-exec-3] org.hibernate.SQL : 选择 userinfo0_.userid 作为 userid1_1_, userinfo0_.enabled 为 enabled2_1_, userinfo0_.password 作为密码3_1_, userinfo0_.role 作为 role4_1_ 从 tuserid 用户信息0_ 在哪里 userinfo0_.userid=? 和 userinfo0_.enabled=? 2018-10-17 20:05:37.701 TRACE 15968 --- [nio-8090-exec-3] ohtype.descriptor.sql.BasicBinder:绑定参数 [1] 作为 [VARCHAR] - [kudelam] 2018-10- 17 20:05:37.701 跟踪 15968 --- [nio-8090-exec-3] o.h.type.descriptor.sql.BasicBinder :绑定参数 [2] 作为 [SMALLINT] - [1] 2018-10-17 20:05:37.715 错误 15968 --- [nio-8090-exec-3] w.a.UsernamePasswordAuthenticationFilter : 发生内部错误 在尝试对用户进行身份验证时。
org.springframework.security.authentication.InternalAuthenticationServiceException: 需要授予权限的文本表示形式
请您看一下并对此有所了解吗?
【问题讨论】:
【参考方案1】:用这种方法代替
GrantedAuthority authority = new SimpleGrantedAuthority(activeUserInfo.getRole());
UserDetails userDetails = (UserDetails)new User(activeUserInfo.getUserName(),
activeUserInfo.getPassword(), Arrays.asList(authority));
做
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
grantedAuthorities.add(new SimpleGrantedAuthority(activeUserInfo.getRole()));
return new org.springframework.security.core.userdetails.User(activeUserInfo.getUsername(),
activeUserInfo.getPassword(),
grantedAuthorities);
【讨论】:
感谢您的提示。不幸的是 - 错误仍然是一样的。当我尝试登录时,我从日志中收到“错误凭据”和信息:2018-10-18 09:09:11.670 ERROR 17208 --- [nio-8090-exec-4] waUsernamePasswordAuthenticationFilter:发生内部错误时试图对用户进行身份验证。 org.springframework.security.authentication.InternalAuthenticationServiceException:需要授予权限的文本表示 您如何存储密码?如果它是纯文本,那么这是一个问题。您需要存储加密格式。 我存储了加密格式的密码。我使用 BCrypt 在线工具加密我的密码:$2y$12$jpyWS0aIW7.jiMN.iAh81egdEfMZh3QlbS9LvoW/nmhFpS48n07y6以上是关于Spring boot - 尝试从 mySQL DB 验证用户 - 需要授予权限的文本表示的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot无法从数据源(mysql)确定jdbc url
无法从 Spring Boot Docker 容器连接到本地 MySQL 数据库服务器