微信公众号授权与Shiro权限框架整合
背景
微信公众号授权之后,想访问本地服务器的资源。
实现
-
创建新的Token类型。Shiro默认用的Token类型是UsernamePasswordToken,仿照UsernamePasswordToken,建一个属于微信用户的Token类型,叫MockToke
private String username; //用户名 public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } @Override public Object getPrincipal() { return this.username; } @Override public Object getCredentials() { return null; //密码返回null,不进行认证 }
-
添加filter类,来处理不同类型的请求到不同的登陆页面
//表明是访问微信资源的请求,省略set方法 private String urlPattern; //微信请求对应跳转页面,省略set方法 private String wxloginUrl; //未登录重定向到登陆页 @Override protected void redirectToLogin(ServletRequest req, ServletResponse resp) throws IOException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String loginUrl; //后台地址跳转到后台登录地址,前台需要登录的跳转到shiro配置的登录地址 //若请求里包含urlPattern,设置loginUrl为微信登录授权页入口 if (request.getRequestURI().indexOf(getUrlPattern())!=-1) { loginUrl = getWxloginUrl(); } else { loginUrl = getLoginUrl(); } WebUtils.issueRedirect(request, response, loginUrl); }
-
修改Shiro配置文件,添加Filters
//添加filter的bean,初始化参数值。
<bean id="userFilter" class="com.smallchill.core.filter.WltxUserFilter">
<property name="urlPattern" value="/wx"/>
<property name="wxloginUrl" value="https://open.weixin.qq.com/connect/oauth2/authorize?appid=YOU_APP_ID&redirect_uri=http%3A%2F%2Fwltx.wx.tunnel.echomod.cn%2FWxAuthServlet&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect"/>
</bean>
shiroFilter配置中添加filter
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 安全管理器 -->
<property name="securityManager" ref="securityManager" />
<!-- 默认的登陆访问url -->
<property name="loginUrl" value="/login" />
<!-- 登陆成功后跳转的url -->
<property name="successUrl" value="/" />
<!-- 没有权限跳转的url -->
<property name="unauthorizedUrl" value="/unauth" />
<!-- 作用于rest无状态的api过滤器 -->
<property name="filters">
<map>
<!--<entry key="rest" >
<bean id="restShiroFilter" class="com.smallchill.core.shiro.RestAuthorizationFilter"></bean>
</entry>-->
<entry key="user" value-ref="userFilter" />
</map>
</property>
<property name="filterChainDefinitions">
<value>
<!--
anon 不需要认证
authc 需要认证
user 验证通过或RememberMe登录的都可以
rest 用于rest无状态服务
-->
/static/** = anon
/wx/** = user
/WxAuthServlet = anon <!-- 微信授权完,redirect跳转路径,因此时还没拿到微信用户信息,设置为不需要认证 -->
/MP_verify_LAdRmyUraSqTJfHH.txt = anon
/login = anon
/WxServlet = anon
/captcha = anon
/** = user
</value>
</property>
</bean>
-
修改Realm类用户验证方法,若为微信用户,免密码验证
/** * 登录认证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { log.info("Shiro登录认证启动"); //若为微信用户token if(authcToken instanceof MockToken){ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(authcToken.getPrincipal(),null,getName()); return info; } IShiro shiroFactory = ShiroManager.me().getDefaultShiroFactory(); UsernamePasswordToken token = (UsernamePasswordToken) authcToken; User user = shiroFactory.user(token.getUsername()); ShiroUser shiroUser = shiroFactory.shiroUser(user); SimpleAuthenticationInfo info = shiroFactory.info(shiroUser, user, getName()); log.info("Shiro登录认证完毕"); return info; }
重写Realm的supports方法,使之支持MockToken
@Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken || token instanceof MockToken; }
-
微信授权通过后,redirect到配置的路径,获取微信用户信息,缓存用户信息,登陆。 以下为WxAuthServlet的部分代码
WxUserInfo userInfo = wxAdapter.getWxUserInfo(accessToken,openId); // 设置要传递的参数 WxUserCatch.catchUserInfo(userInfo); MockToken token = new MockToken(); token.setRememberMe(true); token.setUsername(userInfo.getOpenId()); Subject currentUser = ShiroKit.getSubject(); currentUser.login(token); // 跳转到index.html request.getRequestDispatcher("/wx/index.html").forward(request, response);
网友评论