感慨:大二刚开始学java,只顾埋头照着敲,什么语法什么意思通通不知道,敲完运行看看效果正确就洋洋得意一番。后来慢慢懂了基本语法,基本意思,想实现什么功能就百度一下,面向对象编程成了面向百度编程。开始了抄,第一阶段直接抄,代码实现错误就是辣鸡答案。第二阶段,看看代码的基本如何实现,对它进行一些更改达到自己的预期效果。第三阶段,抄它的思想,从它的思想中获得灵感。到了这个阶段,觉得自己好像什么都会,又好像什么都不会。万一没得抄呢?道友们,开始看源码吧,也不是自己从头到尾看源码,这要弄点东西还不得头发都白了。百度百度博客,看看人家写的它的基本运行过程,看看你卡在哪一步,然后去看看源码哪里错了,再去思考为什么,最后去解决问题。
public class BaseLoginRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("进入用户登录");
// 获取用户名
String userName = (String) token.getPrincipal();
// 通过用户名获取用户对象
PersonInfo personInfo = personInfoService.findById(userName);
if (personInfo == null) {
return null;
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, personInfo.getPassword(), this.getName());
return info;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("进入角色授权");
String userName = (String) getAvailablePrincipal(principals);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
PersonInfo personInfo = personInfoService.findById(userName);
if (personInfo.getRoles().size() > 0) {
Set<String> roleIds=new HashSet<String>();
for (Role role : personInfo.getRoles()) {
roleIds.add(role.getRoleId());
if(role.getAuthoritys().size()>0) {
Set<String> handleMappings=new HashSet<String>();
for(Authority authority:role.getAuthoritys())
handleMappings.add(authority.getHandleMapping());
info.setStringPermissions(handleMappings);
}
}
info.setRoles(roleIds);
}
return info;
}
}
doGetAuthenticationInfo在你认证身份的时候就会进去,doGetAuthorizationInfo授权却始终不进去。
首先,doGetAuthorizationInfo授权不是主动调用的,你得去校验是否有权限时才会去授权。
代码方式使用Subject对象的isPermitted等类似方法去调用,还可以使用注解,具体百度。但我的它会报错:
java.lang.IllegalStateException: Configuration error: No realms have been configured! One or more realms must be present to execute an authorization operation.
at org.apache.shiro.authz.ModularRealmAuthorizer.assertRealmsConfigured(ModularRealmAuthorizer.java:210)
at org.apache.shiro.authz.ModularRealmAuthorizer.isPermitted(ModularRealmAuthorizer.java:220)
at org.apache.shiro.mgt.AuthorizingSecurityManager.isPermitted(AuthorizingSecurityManager.java:113)
at org.apache.shiro.subject.support.DelegatingSubject.isPermitted(DelegatingSubject.java:162)
at com.tczs.util.MyIntercpetor.preHandle(MyIntercpetor.java:35)
查看源码
/**
* Used by the {@link Authorizer Authorizer} implementation methods to ensure that the {@link #setRealms realms}
* has been set. The default implementation ensures the property is not null and not empty.
*
* @throws IllegalStateException if the <tt>realms</tt> property is configured incorrectly.
*/
protected void assertRealmsConfigured() throws IllegalStateException {
Collection<Realm> realms = getRealms();
if (realms == null || realms.isEmpty()) {
String msg = "Configuration error: No realms have been configured! One or more realms must be " +
"present to execute an authorization operation.";
throw new IllegalStateException(msg);
}
}
realms为null,但我看别人的不都是这样配置realms的吗
<!-- 配置多个Realm -->
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
<property name="realms">
<list>
<ref bean="employeeLoginRealm"/>
<ref bean="baseLoginRealm"/>
</list>
</property>
</bean>
<!-- 配置 Shiro 的 SecurityManager Bean. -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="authenticator" ref="authenticator"/>
</bean>
对,是别人的,我也不知道他为什么不报错,我的问题还是要解决的,百度一番,都不可行,还是看源码吧,首先我把自己两个realm都注入到DefaultWebSecurityManager这个类里了,为什么它报null呢,查看DefaultWebSecurityManager类源码,发现他的方法都是和认证有关的,也就是doGetAuthenticationInfo能进去,因为我把我的realm注入到这个类了。现在想来,当时我已经发现这个问题了,但我为什么还花了这么多时间去解决,原因还是太过依赖别人,总想着别人都这样配置的,反而忘了问题的原因。我们认证注入了realm,授权应该也有个类要注入realm,就是我们报错的提示类ModularRealmAuthorizer。
查看源码
public class ModularRealmAuthorizer implements Authorizer, PermissionResolverAware, RolePermissionResolverAware {
/**
* The realms to consult during any authorization check.
*/
protected Collection<Realm> realms;
/**
* A PermissionResolver to be used by <em>all</em> configured realms. Leave <code>null</code> if you wish
* to configure different resolvers for different realms.
*/
protected PermissionResolver permissionResolver;
/**
* A RolePermissionResolver to be used by <em>all</em> configured realms. Leave <code>null</code> if you wish
* to configure different resolvers for different realms.
*/
protected RolePermissionResolver rolePermissionResolver;
果然有realms这个属性,我们再和开始注入认证类时一样注入就行了
<!-- 配置多个Realm -->
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
<property name="realms">
<list>
<ref bean="employeeLoginRealm"/>
<ref bean="baseLoginRealm"/>
</list>
</property>
</bean>
<!-- 配置多个Realm -->
<bean id="authorizer" class="org.apache.shiro.authz.ModularRealmAuthorizer">
<property name="realms">
<list>
<ref bean="employeeLoginRealm"/>
<ref bean="baseLoginRealm"/>
</list>
</property>
</bean>
<!-- 配置 Shiro 的 SecurityManager Bean. -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="authenticator" ref="authenticator"/>
<property name="authorizer" ref="authorizer"/>
</bean>
我的问题已经解决
进入用户登录
Hibernate: select personinfo0_.personId as personId1_10_0_, personinfo0_.createTime as createTi2_10_0_, personinfo0_.employeeId as employee3_10_0_, personinfo0_.password as password4_10_0_, personinfo0_.version as version5_10_0_ from PersonInfo personinfo0_ where personinfo0_.personId=?
进入角色授权
Hibernate: select personinfo0_.personId as personId1_10_0_, personinfo0_.createTime as createTi2_10_0_, personinfo0_.employeeId as employee3_10_0_, personinfo0_.password as password4_10_0_, personinfo0_.version as version5_10_0_ from PersonInfo personinfo0_ where personinfo0_.personId=?
Hibernate: select roles0_.personId as personId2_11_0_, roles0_.roleId as roleId1_11_0_, role1_.roleId as roleId1_15_1_, role1_.createTime as createTi2_15_1_, role1_.remark as remark3_15_1_, role1_.roleName as roleName4_15_1_, role1_.version as version5_15_1_ from PersonMapperRole roles0_ inner join Role role1_ on roles0_.roleId=role1_.roleId where roles0_.personId=?
Hibernate: select authoritys0_.roleId as roleId4_16_0_, authoritys0_.authorityId as authorit2_16_0_, authority1_.authorityId as authorit1_0_1_, authority1_.authorityName as authorit2_0_1_, authority1_.createTime as createTi3_0_1_, authority1_.handleMapping as handleMa4_0_1_, authority1_.iconCls as iconCls5_0_1_, authority1_.iconName as iconName6_0_1_, authority1_.menuId as menuId7_0_1_, authority1_.menuName as menuName8_0_1_, authority1_.version as version9_0_1_ from RoleMapperAuthority authoritys0_ inner join Authority authority1_ on authoritys0_.authorityId=authority1_.authorityId where authoritys0_.roleId=?