I'm using Spring MVC+Security and Oracle 10g. When I try authenticate I get the following error:
Error : PreparedStatementCallback; invalid ResultSet access for SQL [SELECT PAYGATEMANAGER.AUTHENTICATION_PKG.getUser(?) FROM DUAL]; nested exception is java.sql.SQLException: Invalid column index
security.xml:
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"SELECT PAYGA开发者_如何学运维TEMANAGER.AUTHENTICATION_PKG.getUser(?) FROM DUAL"
authorities-by-username-query=
"SELECT PAYGATEMANAGER.AUTHENTICATION_PKG.getAuthorities(?) FROM DUAL" />
</authentication-provider>
</authentication-manager>
PL/SQL:
CREATE OR REPLACE PACKAGE PAYGATEMANAGER.AUTHENTICATION_PKG AS
TYPE T_REFCURSOR IS REF CURSOR;
FUNCTION getUser(username IN VARCHAR2) RETURN T_REFCURSOR;
FUNCTION getAuthorities(username IN VARCHAR2) RETURN T_REFCURSOR;
END AUTHENTICATION_PKG;
CREATE OR REPLACE PACKAGE BODY PAYGATEMANAGER.AUTHENTICATION_PKG AS
FUNCTION getUser(username IN VARCHAR2)
RETURN T_REFCURSOR IS
userInfo T_REFCURSOR;
BEGIN
OPEN userInfo FOR
SELECT
U.NAME AS username ,
P.PASSWORD AS password,
'true' AS enabled
FROM
PAYGATEMANAGER.USERS U INNER JOIN PAYGATEMANAGER.PASSWORDS P
USING(USER_ID)
WHERE
U.NAME = username;
RETURN userInfo;
END;
FUNCTION getAuthorities(username IN VARCHAR2)
RETURN T_REFCURSOR IS
userAuthorities T_REFCURSOR;
BEGIN
OPEN userAuthorities FOR
SELECT
U.NAME AS username ,
UR.ROLE AS authorities
FROM
PAYGATEMANAGER.USERS U INNER JOIN PAYGATEMANAGER.USERS_ROLES UR
USING(USER_ID)
WHERE
U.NAME = username;
RETURN userAuthorities;
END;
END AUTHENTICATION_PKG;
I think the reason is in return type T_REFCURSOR, which is not fetching into username, password, enabled. But how to fix this? To add some functionality in future (e.g. login attempts audit) I think I should do it in PL/SQL functions, not hard coding in SQL.
This definitely won't work with the "out of the box" JdbcDaoImpl (which is what <jdbc-user-service> maps to). I would suggest reviewing the source code of the standard implementation, and then writing your own implementation which implements the Spring Security UserDetailsService, but uses JDBC and CallableStatement under the covers.
You will declare your implementation class as a regular spring bean:
<bean id="MyPlsqlUserDetailsService" class="my.great.JdbcCallableStatementImpl"/>
... and then use the ref attribute on <user-details-service> as follows:
<user-details-service ref="MyPlsqlUserDetailsService"/>
(Note that I'm omitting the intricacy of XML namespaces etc etc, hopefully you understand those).
Good luck!
加载中,请稍侯......
精彩评论